refactor: 四端完成 Options API → script setup + vuex → pinia 迁移

- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup>
- 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录)
- util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入
- 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md)
- 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API
- 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
This commit is contained in:
lifenlong
2026-10-13 07:06:59 +08:00
parent 870bacdd8c
commit 88fc1b0b2a
674 changed files with 71220 additions and 69943 deletions

View File

@@ -2,7 +2,7 @@
<div class="search">
<el-card>
<el-form
ref="searchForm"
ref="searchFormRef"
:model="searchForm"
inline
label-width="70px"
@@ -87,88 +87,90 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import { onBeforeRouteLeave, useRouter } from "vue-router";
import * as API_Shop from "@/api/shops";
export default {
name: "accountStatementBill",
data() {
return {
loading: true,
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
},
data: [],
total: 0,
};
},
methods: {
billStatusText(v) {
const map = { OUT: "已出账", CHECK: "已对账", COMPLETE: "已付款" };
return map[v] || "已付款";
},
billStatusTagType(v) {
const map = { OUT: "primary", CHECK: "warning", COMPLETE: "success" };
return map[v] || "success";
},
init() {
this.getDataList();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.getDataList();
},
handleReset() {
this.searchForm = {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
};
this.getDataList();
},
getDataList() {
this.loading = true;
this.searchForm.billStatus = "OUT";
API_Shop.getBillPage(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
detail(v) {
this.$router.push({
name: "bill-detail",
query: { id: v.id },
});
},
},
mounted() {
this.init();
},
beforeRouteLeave(to, from, next) {
from.meta.keepAlive = false;
next();
},
};
defineOptions({ name: "accountStatementBill" });
const router = useRouter();
const loading = ref(true);
const searchForm = ref({
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
});
const data = ref([]);
const total = ref(0);
// searchFormRef:模板 ref 改名避免与顶层变量互相覆盖
const searchFormRef = ref(null);
onMounted(() => {
init();
});
onBeforeRouteLeave((to, from) => {
from.meta.keepAlive = false;
});
function billStatusText(v) {
const map = { OUT: "已出账", CHECK: "已对账", COMPLETE: "已付款" };
return map[v] || "已付款";
}
function billStatusTagType(v) {
const map = { OUT: "primary", CHECK: "warning", COMPLETE: "success" };
return map[v] || "success";
}
function init() {
getDataList();
}
function changePage(v) {
searchForm.value.pageNumber = v;
getDataList();
}
function changePageSize(v) {
searchForm.value.pageNumber = 1;
searchForm.value.pageSize = v;
getDataList();
}
function handleSearch() {
searchForm.value.pageNumber = 1;
getDataList();
}
function handleReset() {
searchForm.value = {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
};
getDataList();
}
function getDataList() {
loading.value = true;
searchForm.value.billStatus = "OUT";
API_Shop.getBillPage(searchForm.value).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function detail(v) {
router.push({
name: "bill-detail",
query: { id: v.id },
});
}
</script>
<style lang="scss" scoped>
@import "@/styles/table-common.scss";

View File

@@ -292,249 +292,252 @@
</div>
</template>
<script>
<script setup>
import { onBeforeRouteLeave, useRoute } from "vue-router";
import { onMounted, reactive, ref, watch } from "vue";
import * as filters from "@/utils/filters";
import * as API_Shop from "@/api/shops";
import { Message, Modal } from "@/utils/message";
export default {
name: "bill-detail",
data() {
return {
activeTab: "order",
loading: false,
billData: [
{
billPrice: 0,
orderPrice: 0,
siteCouponCommission: 0,
pointSettlementPrice: 0,
kanjiaSettlementPrice: 0,
giftCardSubsidy: 0,
distributionCommission: 0,
commissionPrice: 0,
refundPrice: 0,
siteCouponRefundCommission: 0,
pointRefundSettlementPrice: 0,
kanjiaRefundSettlementPrice: 0,
giftCardRefundSubsidy: 0,
distributionRefundCommission: 0,
refundCommissionPrice: 0,
},
],
data: [
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
],
id: "",
bill: {},
orderData: [],
orderParam: {
pageNumber: 1,
pageSize: 20,
sort: "id",
order: "desc",
startDate: null,
endDate: null,
},
orderTotal: 0,
refundTotal: 0,
billStatusList: [
{ status: "OUT", value: "已出账", title: "生成账单" },
{ status: "CHECK", value: "已对账", title: "商家对账" },
{ status: "PAY", value: "已付款", title: "平台付款" },
{ status: "COMPLETE", value: "已完成", title: "结算完成" },
],
billStatusStep: [],
};
},
methods: {
formatPrice(value) {
return this.$filters.unitPrice(value, "¥");
},
negate(value) {
return 0 - value;
},
isPayFlow(row) {
return row.flowType === "PAY";
},
orderSubsidyTotal(row) {
return (
row.pointSettlementPrice + row.kanjiaSettlementPrice + row.siteCouponCommission
);
},
orderSubsidyDisplay(row) {
if (row.pointSettlementPrice == 0) {
return "-";
}
return this.orderSubsidyTotal(row);
},
orderCommissionDisplay(row) {
return row.commissionPrice == 0 ? "-" : row.commissionPrice;
},
orderDistributionRebateDisplay(row) {
return row.distributionRebate == 0 ? "-" : row.distributionRebate;
},
orderExpenseTotal(row) {
return row.commissionPrice + row.distributionRebate;
},
getBillStatusStep() {
this.billStatusStep = [];
let current = "";
let myCur = false;
let myIdx = 0;
this.billStatusList.map((item, index) => {
if (item.status === this.bill.billStatus) {
myCur = true;
myIdx = index;
current = "";
} else if (!myCur) {
current = "";
} else if (myIdx + 1 === index) {
current = "current";
} else {
current = "future";
}
this.billStatusStep.push({ ...item, className: current });
});
if (this.bill.billStatus === "COMPLETE") {
this.billStatusStep[this.billStatusStep.length - 1].className = "current";
}
},
orderChangePage(v) {
this.orderParam.pageNumber = v;
this.getOrder();
},
orderChangePageSize(v) {
this.orderParam.pageNumber = 1;
this.orderParam.pageSize = v;
this.getOrder();
},
reconciliation() {
this.$Modal.confirm({
title: "确认核对结算单",
content: "您确认要核对此结算单么?",
loading: true,
onOk: () => {
API_Shop.reconciliation(this.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("账单核对成功");
this.init();
}
});
},
});
},
download() {
API_Shop.downloadBill(this.id)
.then((res) => {
const blob = new Blob([res], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
if ("download" in document.createElement("a")) {
const link = document.createElement("a");
link.download = "结算单-" + this.id + ".xlsx";
link.style.display = "none";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
} else {
navigator.msSaveBlob(blob, "结算单-" + this.id + ".xlsx");
}
})
.catch((err) => {
console.log(err);
});
},
init() {
this.id = this.$route.query.id;
this.getDetail();
},
getDetail() {
API_Shop.getBillDetail(this.id).then((res) => {
if (res.success) {
this.bill = res.result;
this.initTable();
this.getOrder();
this.getBillStatusStep();
}
});
},
initTable() {
const bill = this.bill;
const money = (val) => (val === null || val === undefined || val === "" ? 0 : val);
defineOptions({ name: "bill-detail" });
this.data[0].name = "结算单状态";
this.data[0].value = filters.unixSellerBillStatus(bill.billStatus);
this.data[1].name = "结算单号";
this.data[1].value = bill.sn;
this.data[2].name = "店铺名称";
this.data[2].value = bill.storeName;
this.data[3].name = "起止日期";
this.data[3].value = bill.startTime + "~" + bill.endTime;
this.data[4].name = "银行开户名";
this.data[4].value = bill.bankAccountName;
this.data[5].name = "银行账号";
this.data[5].value = bill.bankAccountNumber;
this.data[6].name = "开户行支行名称";
this.data[6].value = bill.bankName;
this.data[7].name = "支行联行号";
this.data[7].value = bill.bankCode;
this.data[8].name = "支付时间";
this.data[8].value = bill.payTime === null ? "未付款" : bill.payTime;
const route = useRoute();
this.billData[0].billPrice = money(this.bill.billPrice);
this.billData[0].orderPrice = money(this.bill.orderPrice);
this.billData[0].siteCouponCommission = money(this.bill.siteCouponCommission);
this.billData[0].pointSettlementPrice = money(this.bill.pointSettlementPrice);
this.billData[0].kanjiaSettlementPrice = money(this.bill.kanjiaSettlementPrice);
this.billData[0].giftCardSubsidy = money(this.bill.giftCardSubsidy);
this.billData[0].distributionCommission = money(this.bill.distributionCommission);
this.billData[0].commissionPrice = money(this.bill.commissionPrice);
this.billData[0].refundPrice = money(this.bill.refundPrice);
this.billData[0].siteCouponRefundCommission = money(this.bill.siteCouponRefundCommission);
this.billData[0].pointRefundSettlementPrice = money(this.bill.pointRefundSettlementPrice);
this.billData[0].kanjiaRefundSettlementPrice = money(this.bill.kanjiaRefundSettlementPrice);
this.billData[0].giftCardRefundSubsidy = money(this.bill.giftCardRefundSubsidy);
this.billData[0].distributionRefundCommission = money(this.bill.distributionRefundCommission);
this.billData[0].refundCommissionPrice = money(this.bill.refundCommissionPrice);
},
getOrder() {
this.loading = true;
API_Shop.getSellerFlow(this.id, this.orderParam).then((res) => {
this.loading = false;
if (res.success) {
this.orderData = res.result.records;
this.orderTotal = res.result.total;
}
});
},
const activeTab = ref("order");
const loading = ref(false);
const billData = ref([
{
billPrice: 0,
orderPrice: 0,
siteCouponCommission: 0,
pointSettlementPrice: 0,
kanjiaSettlementPrice: 0,
giftCardSubsidy: 0,
distributionCommission: 0,
commissionPrice: 0,
refundPrice: 0,
siteCouponRefundCommission: 0,
pointRefundSettlementPrice: 0,
kanjiaRefundSettlementPrice: 0,
giftCardRefundSubsidy: 0,
distributionRefundCommission: 0,
refundCommissionPrice: 0,
},
mounted() {
this.init();
},
watch: {
"$route.query.id"(val) {
this.id = val;
this.getDetail();
},
},
beforeRouteLeave(to, from, next) {
if (to.name === "accountStatementBill" || to.name === "storeBill") {
to.meta.keepAlive = true;
]);
const data = ref([
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
{ name: "计算中", value: 0 },
]);
const id = ref("");
const bill = ref({});
const orderData = ref([]);
const orderParam = reactive({
pageNumber: 1,
pageSize: 20,
sort: "id",
order: "desc",
startDate: null,
endDate: null,
});
const orderTotal = ref(0);
const refundTotal = ref(0);
const billStatusList = ref([
{ status: "OUT", value: "已出账", title: "生成账单" },
{ status: "CHECK", value: "已对账", title: "商家对账" },
{ status: "PAY", value: "已付款", title: "平台付款" },
{ status: "COMPLETE", value: "已完成", title: "结算完成" },
]);
const billStatusStep = ref([]);
onMounted(() => {
init();
});
watch(
() => route.query.id,
(val) => {
id.value = val;
getDetail();
}
);
onBeforeRouteLeave((to, from, next) => {
if (to.name === "accountStatementBill" || to.name === "storeBill") {
to.meta.keepAlive = true;
}
next();
});
function formatPrice(value) {
return filters.unitPrice(value, "¥");
}
function negate(value) {
return 0 - value;
}
function isPayFlow(row) {
return row.flowType === "PAY";
}
function orderSubsidyTotal(row) {
return (
row.pointSettlementPrice + row.kanjiaSettlementPrice + row.siteCouponCommission
);
}
function orderSubsidyDisplay(row) {
if (row.pointSettlementPrice == 0) {
return "-";
}
return orderSubsidyTotal(row);
}
function orderCommissionDisplay(row) {
return row.commissionPrice == 0 ? "-" : row.commissionPrice;
}
function orderDistributionRebateDisplay(row) {
return row.distributionRebate == 0 ? "-" : row.distributionRebate;
}
function orderExpenseTotal(row) {
return row.commissionPrice + row.distributionRebate;
}
function getBillStatusStep() {
billStatusStep.value = [];
let current = "";
let myCur = false;
let myIdx = 0;
billStatusList.value.map((item, index) => {
if (item.status === bill.value.billStatus) {
myCur = true;
myIdx = index;
current = "";
} else if (!myCur) {
current = "";
} else if (myIdx + 1 === index) {
current = "current";
} else {
current = "future";
}
next();
},
};
billStatusStep.value.push({ ...item, className: current });
});
if (bill.value.billStatus === "COMPLETE") {
billStatusStep.value[billStatusStep.value.length - 1].className = "current";
}
}
function orderChangePage(v) {
orderParam.pageNumber = v;
getOrder();
}
function orderChangePageSize(v) {
orderParam.pageNumber = 1;
orderParam.pageSize = v;
getOrder();
}
function reconciliation() {
Modal.confirm({
title: "确认核对结算单",
content: "您确认要核对此结算单么?",
loading: true,
onOk: () => {
API_Shop.reconciliation(id.value).then((res) => {
Modal.remove();
if (res.success) {
Message.success("账单核对成功");
init();
}
});
},
});
}
function download() {
API_Shop.downloadBill(id.value)
.then((res) => {
const blob = new Blob([res], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
if ("download" in document.createElement("a")) {
const link = document.createElement("a");
link.download = "结算单-" + id.value + ".xlsx";
link.style.display = "none";
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
} else {
navigator.msSaveBlob(blob, "结算单-" + id.value + ".xlsx");
}
})
.catch((err) => {
console.log(err);
});
}
function init() {
id.value = route.query.id;
getDetail();
}
function getDetail() {
API_Shop.getBillDetail(id.value).then((res) => {
if (res.success) {
bill.value = res.result;
initTable();
getOrder();
getBillStatusStep();
}
});
}
function initTable() {
const billVal = bill.value;
const money = (val) => (val === null || val === undefined || val === "" ? 0 : val);
data.value[0].name = "结算单状态";
data.value[0].value = filters.unixSellerBillStatus(billVal.billStatus);
data.value[1].name = "结算单号";
data.value[1].value = billVal.sn;
data.value[2].name = "店铺名称";
data.value[2].value = billVal.storeName;
data.value[3].name = "起止日期";
data.value[3].value = billVal.startTime + "~" + billVal.endTime;
data.value[4].name = "银行开户名";
data.value[4].value = billVal.bankAccountName;
data.value[5].name = "银行账号";
data.value[5].value = billVal.bankAccountNumber;
data.value[6].name = "开户行支行名称";
data.value[6].value = billVal.bankName;
data.value[7].name = "支行联行号";
data.value[7].value = billVal.bankCode;
data.value[8].name = "支付时间";
data.value[8].value = billVal.payTime === null ? "未付款" : billVal.payTime;
billData.value[0].billPrice = money(billVal.billPrice);
billData.value[0].orderPrice = money(billVal.orderPrice);
billData.value[0].siteCouponCommission = money(billVal.siteCouponCommission);
billData.value[0].pointSettlementPrice = money(billVal.pointSettlementPrice);
billData.value[0].kanjiaSettlementPrice = money(billVal.kanjiaSettlementPrice);
billData.value[0].giftCardSubsidy = money(billVal.giftCardSubsidy);
billData.value[0].distributionCommission = money(billVal.distributionCommission);
billData.value[0].commissionPrice = money(billVal.commissionPrice);
billData.value[0].refundPrice = money(billVal.refundPrice);
billData.value[0].siteCouponRefundCommission = money(billVal.siteCouponRefundCommission);
billData.value[0].pointRefundSettlementPrice = money(billVal.pointRefundSettlementPrice);
billData.value[0].kanjiaRefundSettlementPrice = money(billVal.kanjiaRefundSettlementPrice);
billData.value[0].giftCardRefundSubsidy = money(billVal.giftCardRefundSubsidy);
billData.value[0].distributionRefundCommission = money(billVal.distributionRefundCommission);
billData.value[0].refundCommissionPrice = money(billVal.refundCommissionPrice);
}
function getOrder() {
loading.value = true;
API_Shop.getSellerFlow(id.value, orderParam).then((res) => {
loading.value = false;
if (res.success) {
orderData.value = res.result.records;
orderTotal.value = res.result.total;
}
});
}
</script>
<style scoped lang="scss">

View File

@@ -2,7 +2,7 @@
<div class="search">
<el-card>
<el-form
ref="searchForm"
ref="searchFormRef"
:model="searchForm"
inline
label-width="70px"
@@ -90,120 +90,121 @@
</div>
</template>
<script>
<script setup>
import { computed, onMounted, ref } from "vue";
import { onBeforeRouteLeave, useRoute } from "vue-router";
import * as API_Shop from "@/api/shops";
import * as API_Finance from "@/api/finance";
import { downloadBlob } from "@/utils/downloadBlob";
import { customRouterPush } from "@/utils/filters";
export default {
name: "storeBill",
data() {
return {
loading: true,
searchForm: {
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
},
data: [],
total: 0,
currentStatus: "ALL",
};
},
computed: {
billStatusTabs() {
return [
{ title: "全部", value: "ALL" },
{ title: "已出账", value: "OUT" },
{ title: "已对账", value: "CHECK" },
{ title: "已完成", value: "COMPLETE" },
];
},
},
methods: {
onStatusTabClick(tab) {
this.billStatusClick(tab.paneName);
},
billStatusClick(name) {
if (name === "ALL" || name === "" || name === undefined || name === null) {
delete this.searchForm.billStatus;
this.currentStatus = "ALL";
} else {
this.searchForm.billStatus = name;
this.currentStatus = name;
}
this.searchForm.pageNumber = 1;
this.getDataList();
},
init() {
this.getDataList();
},
changePage() {
this.getDataList();
},
changePageSize() {
this.searchForm.pageNumber = 1;
this.getDataList();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
handleReset() {
const { billStatus } = this.searchForm;
this.searchForm = {
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
};
if (this.currentStatus !== "ALL") {
this.searchForm.billStatus = billStatus;
}
this.getDataList();
},
getDataList() {
this.loading = true;
API_Shop.getBillPage(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
detail(v) {
this.$filters.customRouterPush({
name: "bill-detail",
query: { id: v.id },
});
},
handleExport() {
const params = { ...this.searchForm };
API_Finance.exportBillList(params).then((blob) => {
downloadBlob(blob, "结算单列表.xlsx");
});
},
},
mounted() {
const billStatus = this.$route.query.billStatus;
if (billStatus) {
this.currentStatus = billStatus;
this.searchForm.billStatus = billStatus;
defineOptions({ name: "storeBill" });
const route = useRoute();
const searchFormRef = ref(null);
const loading = ref(true);
const searchForm = ref({
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
});
const data = ref([]);
const total = ref(0);
const currentStatus = ref("ALL");
const billStatusTabs = computed(() => {
return [
{ title: "全部", value: "ALL" },
{ title: "已出账", value: "OUT" },
{ title: "已对账", value: "CHECK" },
{ title: "已完成", value: "COMPLETE" },
];
});
function onStatusTabClick(tab) {
billStatusClick(tab.paneName);
}
function billStatusClick(name) {
if (name === "ALL" || name === "" || name === undefined || name === null) {
delete searchForm.value.billStatus;
currentStatus.value = "ALL";
} else {
searchForm.value.billStatus = name;
currentStatus.value = name;
}
searchForm.value.pageNumber = 1;
getDataList();
}
function init() {
getDataList();
}
function changePage() {
getDataList();
}
function changePageSize() {
searchForm.value.pageNumber = 1;
getDataList();
}
function handleSearch() {
searchForm.value.pageNumber = 1;
searchForm.value.pageSize = 10;
getDataList();
}
function handleReset() {
const { billStatus } = searchForm.value;
searchForm.value = {
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
};
if (currentStatus.value !== "ALL") {
searchForm.value.billStatus = billStatus;
}
getDataList();
}
function getDataList() {
loading.value = true;
API_Shop.getBillPage(searchForm.value).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
this.init();
},
beforeRouteLeave(to, from, next) {
from.meta.keepAlive = false;
next();
},
};
});
}
function detail(v) {
customRouterPush({
name: "bill-detail",
query: { id: v.id },
});
}
function handleExport() {
const params = { ...searchForm.value };
API_Finance.exportBillList(params).then((blob) => {
downloadBlob(blob, "结算单列表.xlsx");
});
}
onMounted(() => {
const billStatus = route.query.billStatus;
if (billStatus) {
currentStatus.value = billStatus;
searchForm.value.billStatus = billStatus;
}
init();
});
onBeforeRouteLeave((to, from) => {
from.meta.keepAlive = false;
});
</script>
<style lang="scss" scoped>

View File

@@ -27,45 +27,44 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import * as API_Finance from "@/api/finance";
import { downloadBlob } from "@/utils/downloadBlob";
export default {
name: "shop-finance-summary",
data() {
return {
dateRange: [],
summary: null,
};
},
mounted() {
this.loadData();
},
methods: {
buildParams() {
const p = {};
if (this.dateRange?.length === 2) {
p.startDate = this.dateRange[0];
p.endDate = this.dateRange[1];
}
return p;
},
loadData() {
API_Finance.getStoreSummary(this.buildParams()).then((res) => {
if (res.success) this.summary = res.result;
});
},
handleExport() {
API_Finance.exportStoreSummary(this.buildParams()).then((blob) => {
downloadBlob(blob, "店铺周期汇总.xlsx");
});
},
exportFlow() {
API_Finance.exportStoreFlow(this.buildParams()).then((blob) => {
downloadBlob(blob, "店铺流水.xlsx");
});
},
},
};
defineOptions({ name: "shop-finance-summary" });
const dateRange = ref([]);
const summary = ref(null);
onMounted(() => {
loadData();
});
function buildParams() {
const p = {};
if (dateRange.value?.length === 2) {
p.startDate = dateRange.value[0];
p.endDate = dateRange.value[1];
}
return p;
}
function loadData() {
API_Finance.getStoreSummary(buildParams()).then((res) => {
if (res.success) summary.value = res.result;
});
}
function handleExport() {
API_Finance.exportStoreSummary(buildParams()).then((blob) => {
downloadBlob(blob, "店铺周期汇总.xlsx");
});
}
function exportFlow() {
API_Finance.exportStoreFlow(buildParams()).then((blob) => {
downloadBlob(blob, "店铺流水.xlsx");
});
}
</script>

View File

@@ -69,7 +69,7 @@
append-to-body
destroy-on-close
>
<el-form ref="form" :model="formData" label-width="80px">
<el-form ref="formRef" :model="formData" label-width="80px">
<el-form-item label="模板名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入模板名称" />
</el-form-item>
@@ -82,159 +82,163 @@
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import * as API_floor from "@/api/other.js";
export default {
name: "floorList",
data() {
return {
showModal: false,
total: 0,
formData: {
status: false,
name: "",
},
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
pageType: "INDEX",
pageClientType: "PC",
},
loading: false,
pageTypes: [
{ type: "INDEX", title: "首页" },
{ type: "SPECIAL", title: "专题" },
],
list: [],
};
},
mounted() {
this.getTemplateList();
},
methods: {
newTemplate() {
this.$refs.form.validate((valid) => {
if (valid) {
const data = this.formData;
data.status ? (data.pageShow = "OPEN") : (data.pageShow = "CLOSE");
delete data.status;
(data.pageType = this.searchForm.pageType),
(data.pageClientType = "PC");
if (data.id) {
API_floor.updateHome(data.id, data).then((res) => {
this.$Message.success("编辑模板成功");
this.showModal = false;
this.getTemplateList();
});
} else {
API_floor.setHomeSetup(data).then((res) => {
this.$Message.success("新建模板成功");
this.showModal = false;
this.getTemplateList();
});
}
} else {
this.loading = false;
}
});
},
import { Message, Modal } from "@/utils/message";
handleTabChange(type) {
this.searchForm.pageNumber = 1;
this.searchForm.pageType = type;
this.getTemplateList();
},
defineOptions({ name: "floorList" });
createTemp() {
this.$refs.form?.resetFields();
this.formData = { status: false, name: "" };
this.showModal = true;
},
const router = useRouter();
Template(item) {
item.status = item.pageShow;
this.formData = { ...item };
this.showModal = true;
},
const showModal = ref(false);
const total = ref(0);
const formData = ref({
status: false,
name: "",
});
const searchForm = reactive({
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
pageType: "INDEX",
pageClientType: "PC",
});
const loading = ref(false);
const pageTypes = ref([
{ type: "INDEX", title: "首页" },
{ type: "SPECIAL", title: "专题" },
]);
const list = ref([]);
decorate(val) {
const data = { id: val.id, pageShow: val.pageShow, pageType: this.searchForm.pageType };
// formRef:模板 ref 改名避免与顶层变量互相覆盖
const formRef = ref(null);
this.$router.push({
name: "renovation",
query: data,
});
},
onMounted(() => {
getTemplateList();
});
changePageNum(val) {
this.searchForm.pageNumber = val;
this.getTemplateList();
},
changePageSize(val) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = val;
this.getTemplateList();
},
getTemplateList() {
this.loading = true;
API_floor.getHomeList(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.total = res.result.total;
this.list = res.result.records;
this.list.forEach((e) => {
if (e.pageShow === "OPEN") {
e.pageShow = true;
} else {
e.pageShow = false;
}
});
}
});
},
beforeRelease(row) {
if (row.pageShow) {
this.$Message.warning(
this.total === 1
? "当前为唯一页面,无法关闭"
: "请直接开启其他页面,当前页面会自动关闭"
);
return false;
}
return new Promise((resolve, reject) => {
API_floor.releasePageHome(row.id).then((res) => {
if (res && res.success) {
this.$Message.success("发布模板成功");
resolve(true);
this.getTemplateList();
} else {
reject(new Error("release failed"));
}
}).catch(() => {
reject(new Error("release failed"));
function newTemplate() {
formRef.value.validate((valid) => {
if (valid) {
const data = formData.value;
data.status ? (data.pageShow = "OPEN") : (data.pageShow = "CLOSE");
delete data.status;
(data.pageType = searchForm.pageType),
(data.pageClientType = "PC");
if (data.id) {
API_floor.updateHome(data.id, data).then((res) => {
Message.success("编辑模板成功");
showModal.value = false;
getTemplateList();
});
});
},
confirmDel(id) {
this.$Modal.confirm({
title: "提示",
content: "删除此模板?",
onOk: () => this.delTemplate(id),
});
},
delTemplate(id) {
API_floor.removePageHome(id).then((res) => {
if (res.success) {
this.$Message.success("删除模板成功");
this.getTemplateList();
} else {
API_floor.setHomeSetup(data).then((res) => {
Message.success("新建模板成功");
showModal.value = false;
getTemplateList();
});
}
} else {
loading.value = false;
}
});
}
function handleTabChange(type) {
searchForm.pageNumber = 1;
searchForm.pageType = type;
getTemplateList();
}
function createTemp() {
formRef.value?.resetFields();
formData.value = { status: false, name: "" };
showModal.value = true;
}
function Template(item) {
item.status = item.pageShow;
formData.value = { ...item };
showModal.value = true;
}
function decorate(val) {
const data = { id: val.id, pageShow: val.pageShow, pageType: searchForm.pageType };
router.push({
name: "renovation",
query: data,
});
}
function changePageNum(val) {
searchForm.pageNumber = val;
getTemplateList();
}
function changePageSize(val) {
searchForm.pageNumber = 1;
searchForm.pageSize = val;
getTemplateList();
}
function getTemplateList() {
loading.value = true;
API_floor.getHomeList(searchForm).then((res) => {
loading.value = false;
if (res.success) {
total.value = res.result.total;
list.value = res.result.records;
list.value.forEach((e) => {
if (e.pageShow === "OPEN") {
e.pageShow = true;
} else {
e.pageShow = false;
}
});
},
},
};
}
});
}
function beforeRelease(row) {
if (row.pageShow) {
Message.warning(
total.value === 1
? "当前为唯一页面,无法关闭"
: "请直接开启其他页面,当前页面会自动关闭"
);
return false;
}
return new Promise((resolve, reject) => {
API_floor.releasePageHome(row.id).then((res) => {
if (res && res.success) {
Message.success("发布模板成功");
resolve(true);
getTemplateList();
} else {
reject(new Error("release failed"));
}
}).catch(() => {
reject(new Error("release failed"));
});
});
}
function confirmDel(id) {
Modal.confirm({
title: "提示",
content: "删除此模板?",
onOk: () => delTemplate(id),
});
}
function delTemplate(id) {
API_floor.removePageHome(id).then((res) => {
if (res.success) {
Message.success("删除模板成功");
getTemplateList();
}
});
}
</script>
<style lang="scss" scoped>

View File

@@ -10,7 +10,7 @@
:key="index"
:index="index"
:setting="zone"
:ref="`zone${index}`"
:ref="(el) => setZoneRef(el, index)"
@delItem="removeItem($event)"
@changeInfo="changeInfo($event)"
></zone>
@@ -62,158 +62,185 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted, getCurrentInstance } from "vue";
import Zone from "./Zone";
import addItem from "../directives/addItem";
import vAddItem from "../directives/addItem";
export default {
name: "HotZone",
data() {
return {
zones: [],
};
defineOptions({ name: "HotZone" });
const props = defineProps({
image: {
type: String,
required: true,
},
props: {
image: {
type: String,
required: true,
},
zonesInit: {
type: Array,
default: () => [],
},
max: {
type: Number,
},
zonesInit: {
type: Array,
default: () => [],
},
mounted() {
this.zones = this.zonesInit.concat();
max: {
type: Number,
},
methods: {
async addHotzone() {
let perInfo = {
topPer: 0.15,
leftPer: 0.3,
widthPer: 0.2,
heightPer: 0.2,
img: "",
link: "",
type: "",
title: "",
};
let images = await this.getImageSize(this.image);
if (images) {
if (images.height >= 1000) {
perInfo.heightPer = this.convertNumberToDecimal(images.height) / (images.height / 1000);
} else {
perInfo.heightPer = this.convertNumberToDecimal(images.height);
}
perInfo.widthPer = this.convertNumberToDecimal(images.width) / 2;
}
this.addItem(perInfo);
},
convertNumberToDecimal(num) {
if (num >= 10000) {
return num / 100000;
} else if (num >= 1000) {
return num / 10000;
} else if (num >= 100) {
return num / 1000;
} else if (num >= 10) {
return num / 100;
}
},
getImageSize(url) {
return new Promise(function (resolve, reject) {
let image = new Image();
image.onload = function () {
resolve({
width: image.width,
height: image.height,
});
};
image.onerror = function () {
reject(new Error("error"));
};
image.src = url;
});
const emit = defineEmits([
"choose",
"erase",
"overRange",
"remove",
"add",
"change",
]);
const zones = ref([]);
const zoneRefs = ref([]);
const instance = getCurrentInstance();
onMounted(() => {
zones.value = props.zonesInit.concat();
});
// v-for 内的动态 ref:按 index 收集 Zone 组件实例
function setZoneRef(el, index) {
if (el) zoneRefs.value[index] = el;
}
async function addHotzone() {
let perInfo = {
topPer: 0.15,
leftPer: 0.3,
widthPer: 0.2,
heightPer: 0.2,
img: "",
link: "",
type: "",
title: "",
};
let images = await getImageSize(props.image);
if (images) {
if (images.height >= 1000) {
perInfo.heightPer = convertNumberToDecimal(images.height) / (images.height / 1000);
} else {
perInfo.heightPer = convertNumberToDecimal(images.height);
}
perInfo.widthPer = convertNumberToDecimal(images.width) / 2;
}
addItem(perInfo);
}
function convertNumberToDecimal(num) {
if (num >= 10000) {
return num / 100000;
} else if (num >= 1000) {
return num / 10000;
} else if (num >= 100) {
return num / 1000;
} else if (num >= 10) {
return num / 100;
}
}
function getImageSize(url) {
return new Promise(function (resolve, reject) {
let image = new Image();
image.onload = function () {
resolve({
width: image.width,
height: image.height,
});
},
editZone(index) {
this.$refs[`zone${index}`][0].showModalFn(index);
},
delZone(index) {
this.$refs[`zone${index}`][0].delItem(index);
},
showZoneText(zone) {
switch (zone.type) {
case "goods":
return `商品:${zone.goodsName}`;
case "category":
return `分类:${zone.name}`;
case "shops":
return `店铺:${zone.storeName}`;
case "pages":
return `文章:${zone.title}`;
case "marketing":
return `促销活动商品:${zone.goodsName}`;
case "other":
return `${zone.title}`;
default:
return "请选择跳转链接";
}
},
changeInfo(res) {
let { info, index, zoneInfo } = res;
info = { ...zoneInfo, ...info };
// 改变热区并发送change通知
Object.assign(this.zones[index], info);
this.hasChange("changeInfo");
this.$forceUpdate();
},
addItem(setting) {
this.zones.push(setting);
this.$emit("choose");
// this.hasChange() 不应该发送通知,mouseup判定成功才应该发
// this.$emit('add', setting)
},
eraseItem(index = this.zones.length - 1) {
this.zones.splice(index, 1);
this.$emit("erase", index);
},
isOverRange() {
let { max, zones } = this;
};
image.onerror = function () {
reject(new Error("error"));
};
image.src = url;
});
}
return max && zones.length > max;
},
overRange() {
const index = this.zones.length - 1;
function editZone(index) {
zoneRefs.value[index].showModalFn(index);
}
this.zones.splice(index, 1);
this.$emit("overRange", index);
},
removeItem(index = this.zones.length - 1) {
this.zones.splice(index, 1);
this.hasChange("removeItem");
this.$emit("remove", index);
},
changeItem(info, isAdd) {
const index = this.zones.length - 1;
// 改变热区并发送change通知
Object.assign(this.zones[index], info);
this.hasChange("changeItem");
isAdd && this.$emit("add", this.zones[index]);
},
hasChange(from) {
this.$emit("change", this.zones);
},
},
directives: {
addItem,
},
components: {
Zone,
},
};
function delZone(index) {
zoneRefs.value[index].delItem(index);
}
function showZoneText(zone) {
switch (zone.type) {
case "goods":
return `商品:${zone.goodsName}`;
case "category":
return `分类:${zone.name}`;
case "shops":
return `店铺:${zone.storeName}`;
case "pages":
return `文章:${zone.title}`;
case "marketing":
return `促销活动商品:${zone.goodsName}`;
case "other":
return `${zone.title}`;
default:
return "请选择跳转链接";
}
}
function changeInfo(res) {
let { info, index, zoneInfo } = res;
info = { ...zoneInfo, ...info };
// 改变热区并发送change通知
Object.assign(zones.value[index], info);
hasChange("changeInfo");
instance.proxy.$forceUpdate();
}
function addItem(setting) {
zones.value.push(setting);
emit("choose");
// this.hasChange() 不应该发送通知,mouseup判定成功才应该发
// this.$emit('add', setting)
}
function eraseItem(index = zones.value.length - 1) {
zones.value.splice(index, 1);
emit("erase", index);
}
function isOverRange() {
return props.max && zones.value.length > props.max;
}
function overRange() {
const index = zones.value.length - 1;
zones.value.splice(index, 1);
emit("overRange", index);
}
function removeItem(index = zones.value.length - 1) {
zones.value.splice(index, 1);
hasChange("removeItem");
emit("remove", index);
}
function changeItem(info, isAdd) {
const index = zones.value.length - 1;
// 改变热区并发送change通知
Object.assign(zones.value[index], info);
hasChange("changeItem");
isAdd && emit("add", zones.value[index]);
}
function hasChange(from) {
emit("change", zones.value);
}
// v-add-item 指令通过 binding.instance 调用以下方法/读取 zones
defineExpose({
zones,
addItem,
eraseItem,
isOverRange,
overRange,
changeItem,
});
</script>
<style scoped lang="scss">

View File

@@ -85,162 +85,165 @@
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
<!-- 选择图片 -->
<el-dialog width="1200px" v-model="picModelFlag">
<ossManage @callback="callbackSelected" :isComponent="true" :initialize="picModelFlag" ref="ossManage"/>
<ossManage @callback="callbackSelected" :isComponent="true" :initialize="picModelFlag" ref="ossManageRef"/>
</el-dialog>
</li>
</template>
<script>
import changeSize from "../directives/changeSize";
import dragItem from "../directives/dragItem";
// import ossManage from "@/views/sys/oss-manage/ossManage";
<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
// 自定义指令:script setup 中以 vXxx 命名的顶层变量即注册为指令
import vChangeSize from "../directives/changeSize";
import vDragItem from "../directives/dragItem";
import ossManage from "@/views/sys/oss-manage/ossManage";
import { formatLinkType } from "@/utils/filters";
export default {
name: "Zone",
components: {
ossManage,
},
defineOptions({ name: "Zone" });
data() {
return {
zoneTop: "",
zoneLeft: "",
zoneWidth: "",
zoneHeight: "",
hideZone: false,
tooSmall: false,
showModal: false,
picModelFlag: false,
currentIndex: 0,
currentShowIndex: -1,
zoneForm: {
img: "",
link: "",
type: "",
},
};
},
props: ["index", "setting"],
mounted() {
this.setZoneInfo(this.setting);
},
methods: {
setZoneInfo(val) {
this.zoneTop = this.getZoneStyle(val.topPer);
this.zoneLeft = this.getZoneStyle(val.leftPer);
this.zoneWidth = this.getZoneStyle(val.widthPer);
this.zoneHeight = this.getZoneStyle(val.heightPer);
this.tooSmall = val.widthPer < 0.01 && val.heightPer < 0.01;
this.zoneForm.link = val.link;
this.settingZone(val);
},
handlehideZone(isHide = true) {
if (this.hideZone === isHide) {
return;
}
const props = defineProps(["index", "setting"]);
const emit = defineEmits(["changeInfo", "delItem"]);
this.hideZone = isHide;
},
changeInfo(info = {}) {
const { index } = this;
const zoneTop = ref("");
const zoneLeft = ref("");
const zoneWidth = ref("");
const zoneHeight = ref("");
const hideZone = ref(false);
const tooSmall = ref(false);
const showModal = ref(false);
const picModelFlag = ref(false);
const currentIndex = ref(0);
const currentShowIndex = ref(-1);
const zoneForm = reactive({
img: "",
link: "",
type: "",
});
// 历史遗留:原 Options 写法 this.selectedNav 未在 data 声明(只赋值未读取),此处补声明仅作占位
const selectedNav = ref(null);
this.$emit("changeInfo", {
info,
index,
zoneInfo: this.zoneForm,
});
},
showModalFn(index) {
this.showModal = true;
this.currentIndex = index;
},
// 选择图片
handleSelectImg() {
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
// 选择图片回调
callbackSelected(item) {
this.picModelFlag = false;
this.zoneForm.img = item.url;
},
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const liliDialog = ref(null);
const ossManageRef = ref(null);
// 调起选择链接弹窗
handleSelectLink(item, index) {
if (item) this.selectedNav = item;
this.$refs.liliDialog.open("link");
},
// 已选链接
selectedLink(val) {
this.zoneForm.link = this.$filters.formatLinkType(val);
this.settingZone(val);
this.changeInfo(this.zoneForm);
this.showModal = false;
},
settingZone(val) {
this.zoneForm.type = val.___type || val.type;
this.zoneForm.title = val.title;
switch (val.___type) {
case "goods":
this.zoneForm.id = val.id;
this.zoneForm.goodsId = val.goodsId;
this.zoneForm.goodsName = val.goodsName;
break;
case "category":
this.zoneForm.id = val.allId;
this.zoneForm.name = val.name;
break;
case "shops":
this.zoneForm.id = val.id;
this.zoneForm.storeName = val.storeName;
break;
case "pages":
this.zoneForm.id = val.id;
this.zoneForm.___path = val.___path;
this.zoneForm.title = val.title;
break;
case "marketing":
this.zoneForm.id = val.id;
this.zoneForm.goodsId = val.goodsId;
this.zoneForm.goodsName = val.goodsName;
break;
default:
break;
}
},
saveZone() {},
cancelZone() {
this.showModal = false;
},
delZone() {
this.delItem(this.currentIndex);
},
delItem(index) {
this.$emit("delItem", index);
},
getZoneStyle(val) {
return `${(val || 0) * 100}%`;
},
},
onMounted(() => {
setZoneInfo(props.setting);
});
watch: {
setting: {
handler: function (val) {
this.setZoneInfo(val);
},
deep: true,
},
function setZoneInfo(val) {
zoneTop.value = getZoneStyle(val.topPer);
zoneLeft.value = getZoneStyle(val.leftPer);
zoneWidth.value = getZoneStyle(val.widthPer);
zoneHeight.value = getZoneStyle(val.heightPer);
tooSmall.value = val.widthPer < 0.01 && val.heightPer < 0.01;
zoneForm.link = val.link;
settingZone(val);
}
function handlehideZone(isHide = true) {
if (hideZone.value === isHide) {
return;
}
hideZone.value = isHide;
}
function changeInfo(info = {}) {
const { index } = props;
emit("changeInfo", {
info,
index,
zoneInfo: zoneForm,
});
}
function showModalFn(index) {
showModal.value = true;
currentIndex.value = index;
}
// 选择图片
function handleSelectImg() {
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
// 选择图片回调
function callbackSelected(item) {
picModelFlag.value = false;
zoneForm.img = item.url;
}
// 调起选择链接弹窗
function handleSelectLink(item, index) {
// 历史遗留:selectedNav 只赋值未读取,原样保留
if (item) selectedNav.value = item;
liliDialog.value.open("link");
}
// 已选链接
function selectedLink(val) {
zoneForm.link = formatLinkType(val);
settingZone(val);
changeInfo(zoneForm);
showModal.value = false;
}
function settingZone(val) {
zoneForm.type = val.___type || val.type;
zoneForm.title = val.title;
switch (val.___type) {
case "goods":
zoneForm.id = val.id;
zoneForm.goodsId = val.goodsId;
zoneForm.goodsName = val.goodsName;
break;
case "category":
zoneForm.id = val.allId;
zoneForm.name = val.name;
break;
case "shops":
zoneForm.id = val.id;
zoneForm.storeName = val.storeName;
break;
case "pages":
zoneForm.id = val.id;
zoneForm.___path = val.___path;
zoneForm.title = val.title;
break;
case "marketing":
zoneForm.id = val.id;
zoneForm.goodsId = val.goodsId;
zoneForm.goodsName = val.goodsName;
break;
default:
break;
}
}
function saveZone() {}
function cancelZone() {
showModal.value = false;
}
function delZone() {
delItem(currentIndex.value);
}
function delItem(index) {
emit("delItem", index);
}
function getZoneStyle(val) {
return `${(val || 0) * 100}%`;
}
watch(
() => props.setting,
(val) => {
setZoneInfo(val);
},
directives: {
changeSize,
dragItem,
},
};
{ deep: true }
);
// 父组件 Hotzone.vue 通过 $refs 调用 showModalFn / delItem
defineExpose({
showModalFn,
delItem,
});
</script>
<style scoped lang="scss">

View File

@@ -11,7 +11,7 @@
>
<template v-if="flag && hotzoneRes">
<hotzone
ref="hotzone"
ref="hotzoneRef"
:zonesInit="hotzoneRes.zoneInfo"
:image="hotzoneRes.img"
@change="changeHotzone"
@@ -23,47 +23,50 @@
</template>
</el-dialog>
</template>
<script>
<script setup>
import { ref } from "vue";
import hotzone from "./components/Hotzone.vue";
export default {
components: {
hotzone,
},
data() {
return {
flag: false,
hotzoneRes: null,
};
},
methods: {
changeHotzone(info) {
if (this.hotzoneRes) {
this.hotzoneRes.zoneInfo = info;
}
this.$emit("changeZone", info);
},
clickClose() {
this.flag = false;
this.hotzoneRes = null;
this.$emit("closeFlag", false);
},
clickOK() {
this.clickClose();
},
open(val) {
this.hotzoneRes = val || null;
if (this.hotzoneRes && !this.hotzoneRes.zoneInfo) {
this.hotzoneRes.zoneInfo = [];
}
this.flag = true;
},
close() {
this.flag = false;
this.hotzoneRes = null;
},
},
const emit = defineEmits(["changeZone", "closeFlag"]);
const flag = ref(false);
const hotzoneRes = ref(null);
// hotzoneRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const hotzoneRef = ref(null);
const changeHotzone = (info) => {
if (hotzoneRes.value) {
hotzoneRes.value.zoneInfo = info;
}
emit("changeZone", info);
};
const clickClose = () => {
flag.value = false;
hotzoneRes.value = null;
emit("closeFlag", false);
};
const clickOK = () => {
clickClose();
};
const open = (val) => {
hotzoneRes.value = val || null;
if (hotzoneRes.value && !hotzoneRes.value.zoneInfo) {
hotzoneRes.value.zoneInfo = [];
}
flag.value = true;
};
const close = () => {
flag.value = false;
hotzoneRes.value = null;
};
// decorate.vue 通过 hotzoneRef.value.open(val) 调用
defineExpose({ open, close });
</script>
<style scoped lang="scss">
:deep(.el-dialog__body) {

View File

@@ -130,138 +130,145 @@
</table>
</div>
</el-dialog>
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
<liliDialog ref="liliDialogRef" @selectedLink="selectedLink"></liliDialog>
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
<ossManage
@callback="callbackSelected"
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, nextTick, onMounted } from "vue";
import { ShoppingCart } from "@element-plus/icons-vue";
import logoImg from "@/assets/logo.png";
import Draggable from "vuedraggable";
import ModelFormItem from "./modelFormItem.vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
name: "modelForm",
components: {
Draggable,
ModelFormItem,
ossManage,
ShoppingCart,
},
props: ["data"],
data() {
return {
logoImg,
picModelFlag: false,
showModal: false,
showModalNav: false,
selectedNav: null,
promotionTags: ["买2免1", "领200神券", "199减100", "母婴5折抢", "充100送20"],
topAdvert: {
type: "topAdvert",
img: "",
url: "",
bgColor: "#de000d",
size: "1200*80",
},
currentIndex: 0,
navList: {
type: "navBar",
list: [
{ name: "秒杀", url: "", title: "" },
{ name: "闪购", url: "", title: "" },
{ name: "优惠券", url: "", title: "" },
{ name: "拍卖", url: "", title: "" },
{ name: "服装城", url: "", title: "" },
],
},
};
},
mounted() {
document.body.ondrop = function (event) {
let isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
if (isFirefox) {
event.preventDefault();
event.stopPropagation();
}
};
},
methods: {
getModelItemKey(element) {
return element.model || element.key || element.type;
import { formatLinkType } from "@/utils/filters";
defineOptions({ name: "modelForm" });
const props = defineProps(["data"]);
const picModelFlag = ref(false);
const showModal = ref(false);
const showModalNav = ref(false);
const selectedNav = ref(null);
const promotionTags = ref(["买2免1", "领200神券", "199减100", "母婴5折抢", "充100送20"]);
const topAdvert = ref({
type: "topAdvert",
img: "",
url: "",
bgColor: "#de000d",
size: "1200*80",
});
const currentIndex = ref(0);
const navList = ref({
type: "navBar",
list: [
{ name: "秒杀", url: "", title: "" },
{ name: "闪购", url: "", title: "" },
{ name: "优惠券", url: "", title: "" },
{ name: "拍卖", url: "", title: "" },
{ name: "服装城", url: "", title: "" },
],
});
const liliDialogRef = ref(null);
const ossManageRef = ref(null);
// 父组件 renovation.vue 通过 $refs.modelForm 读取并整体赋值 navList / topAdvert
defineExpose({ navList, topAdvert });
onMounted(() => {
document.body.ondrop = function (event) {
let isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
if (isFirefox) {
event.preventDefault();
event.stopPropagation();
}
};
});
function getModelItemKey(element) {
return element.model || element.key || element.type;
}
function handleSelectLink(item, index) {
if (item) selectedNav.value = item;
liliDialogRef.value.open("link");
currentIndex.value = index;
}
function selectedLink(val) {
if (showModalNav.value) {
selectedNav.value.url = formatLinkType(val);
selectedNav.value.type = val.___type === "other" && val.url === "" ? "link" : "other";
} else {
topAdvert.value.url = formatLinkType(val);
topAdvert.value.type = val.___type === "other" && val.url === "" ? "link" : "other";
}
navList.value.list[currentIndex.value].title = val.title;
}
function handleDelNav(index) {
navList.value.list.splice(index, 1);
}
function handleAddNav() {
navList.value.list.push({ name: "", url: "", title: "" });
nextTick(() => {
selectedNav.value = navList.value.list[navList.value.list.length - 1];
});
}
function handleMoveEnd({ newIndex, oldIndex }) {
console.log("index", newIndex, oldIndex);
}
function handleModel(type) {
if (type == "topAdvert") {
showModal.value = true;
} else {
showModalNav.value = true;
}
}
function handleSelectImg() {
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
function callbackSelected(item) {
picModelFlag.value = false;
topAdvert.value.img = item.url;
}
function handleModelAdd(evt) {
const newIndex = evt.newIndex;
const current = props.data.list[newIndex];
if (!current || current.key) {
return;
}
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
props.data.list[newIndex] = {
...JSON.parse(JSON.stringify(current)),
options: {
...current.options,
},
handleSelectLink(item, index) {
if (item) this.selectedNav = item;
this.$refs.liliDialog.open("link");
this.currentIndex = index;
},
selectedLink(val) {
if (this.showModalNav) {
this.selectedNav.url = this.$filters.formatLinkType(val);
this.selectedNav.type = val.___type === "other" && val.url === "" ? "link" : "other";
} else {
this.topAdvert.url = this.$filters.formatLinkType(val);
this.topAdvert.type = val.___type === "other" && val.url === "" ? "link" : "other";
}
this.navList.list[this.currentIndex].title = val.title;
},
handleDelNav(index) {
this.navList.list.splice(index, 1);
},
handleAddNav() {
this.navList.list.push({ name: "", url: "", title: "" });
this.$nextTick(() => {
this.selectedNav = this.navList.list[this.navList.list.length - 1];
});
},
handleMoveEnd({ newIndex, oldIndex }) {
console.log("index", newIndex, oldIndex);
},
handleModel(type) {
if (type == "topAdvert") {
this.showModal = true;
} else {
this.showModalNav = true;
}
},
handleSelectImg() {
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
callbackSelected(item) {
this.picModelFlag = false;
this.topAdvert.img = item.url;
},
handleModelAdd(evt) {
const newIndex = evt.newIndex;
const current = this.data.list[newIndex];
if (!current || current.key) {
return;
}
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
this.data.list[newIndex] = {
...JSON.parse(JSON.stringify(current)),
options: {
...current.options,
},
key,
model: current.type + "_" + key,
};
},
},
};
key,
model: current.type + "_" + key,
};
}
</script>
<style lang="scss" scoped>
@import "./modelList/setup-box.scss";

View File

@@ -256,13 +256,14 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { nextTick, ref } from "vue";
import ModelCarousel from "./modelList/carousel.vue";
import ModelCarousel1 from "./modelList/carousel1.vue";
import ModelCarousel2 from "./modelList/carousel2.vue";
@@ -281,98 +282,82 @@ import onlyGoodsModel from "./modelList/onlyGoodsModel.vue";
import oneRowThreeColumns from "./modelList/oneRowThreeColumns.vue";
import seckillOnlyAlbum from "./modelList/seckill-only-album.vue";
import decorateImg from "@/assets/nav/decorate.png";
export default {
name: "modelFormItem",
props: ["element", "select", "index", "data"],
components: {
ModelCarousel,
ModelCarousel1,
ModelCarousel2,
Recommend,
NewGoodsSort,
FirstPageAdvert,
NotEnough,
Seckill,
goodsType,
ossManage,
oneRowThreeColumns,
"seckill-only-album":seckillOnlyAlbum,
onlyGoodsModel,
mixModel,
forYour
},
data() {
return {
decorateImg,
showModal: false, // modal显隐
selected: {}, // 弹窗编辑草稿
editTarget: null, // 确定后写回的原数据
picModelFlag: false, // 图片选择器
};
},
methods: {
cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
},
// 编辑模块
handleSelectModel(item) {
this.editTarget = item;
this.selected = this.cloneItem(item);
this.showModal = true;
},
// 删除模块
handleModelDelete() {
this.$Modal.confirm({
title: "提示",
content: "<p>确定删除当前模块吗?</p>",
onOk: () => {
this.$nextTick(() => {
this.data.list.splice(this.index, 1);
});
},
});
},
handleSelectLink(item, index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
},
// 确定选择链接
selectedLink(val) {
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
import { Modal } from "@/utils/message";
import { formatLinkType } from "@/utils/filters";
handleSelectImg() {
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
defineOptions({ name: "modelFormItem" });
const props = defineProps(["element", "select", "index", "data"]);
const showModal = ref(false); // modal显隐
const selected = ref({}); // 弹窗编辑草稿
const editTarget = ref(null); // 确定后写回的原数据
const picModelFlag = ref(false); // 图片选择器
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const liliDialog = ref(null);
const ossManageRef = ref(null);
function cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
}
// 编辑模块
function handleSelectModel(item) {
editTarget.value = item;
selected.value = cloneItem(item);
showModal.value = true;
}
// 删除模块
function handleModelDelete() {
Modal.confirm({
title: "提示",
content: "<p>确定删除当前模块吗?</p>",
onOk: () => {
nextTick(() => {
props.data.list.splice(props.index, 1);
});
},
// 回显图片
callbackSelected(val) {
this.picModelFlag = false;
if (!val?.url) return;
this.selected.img = val.url;
},
handleCancelModal() {
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleConfirmModal() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
},
};
});
}
function handleSelectLink(item, index) {
// 调起选择链接弹窗
liliDialog.value.open("link");
}
// 确定选择链接
function selectedLink(val) {
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
function handleSelectImg() {
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
// 回显图片
function callbackSelected(val) {
picModelFlag.value = false;
if (!val?.url) return;
selected.value.img = val.url;
}
function handleCancelModal() {
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleConfirmModal() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
</script>
<style lang="scss" scoped>
@import "./modelList/setup-box.scss";

View File

@@ -123,77 +123,77 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, reactive, nextTick, getCurrentInstance } from "vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
name: "modelCarousel",
props: ["data"],
components: {
ossManage,
},
data() {
return {
showModal: false, // modal显隐
selected: null, // 已选数据
picModelFlag: false, // 选择图片modal
userInfo: {},
articleList: [
{ title: "促销计算规则" },
{ title: "商家申请开店" },
{ title: "商家账号注册" },
{ title: "促销计算规则" },
],
};
},
import { formatLinkType } from "@/utils/filters";
methods: {
handleSelectModel() {
// 编辑模块
this.showModal = true;
},
// 添加轮播图
handleAdd() {
this.data.options.list.push({ img: "", url: "", type: "" });
this.$forceUpdate();
},
handleSelectLink(item) {
// 选择链接
this.$refs.liliDialog.open("link");
this.selected = item;
},
callbackSelected(item) {
// 选择图片回调
this.picModelFlag = false;
this.selected.img = item.url;
},
handleDel(index) {
// 删除图片
this.data.options.list.splice(index, 1);
},
selectedLink(val) {
// 选择链接回调
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
// 选择图片
handleSelectImg(item) {
this.selected = item;
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
},
};
defineOptions({ name: "modelCarousel" });
const props = defineProps(["data"]);
const { proxy } = getCurrentInstance();
const showModal = ref(false); // modal显隐
const selected = ref(null); // 已选数据
const picModelFlag = ref(false); // 选择图片modal
const userInfo = reactive({});
const articleList = ref([
{ title: "促销计算规则" },
{ title: "商家申请开店" },
{ title: "商家账号注册" },
{ title: "促销计算规则" },
]);
const liliDialog = ref(null);
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const ossManageRef = ref(null);
function handleSelectModel() {
// 编辑模块
showModal.value = true;
}
// 添加轮播图
function handleAdd() {
props.data.options.list.push({ img: "", url: "", type: "" });
proxy.$forceUpdate();
}
function handleSelectLink(item) {
// 选择链接
liliDialog.value.open("link");
selected.value = item;
}
function callbackSelected(item) {
// 选择图片回调
picModelFlag.value = false;
selected.value.img = item.url;
}
function handleDel(index) {
// 删除图片
props.data.options.list.splice(index, 1);
}
function selectedLink(val) {
// 选择链接回调
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
// 选择图片
function handleSelectImg(item) {
selected.value = item;
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
</script>
<style scoped lang="scss">

View File

@@ -84,76 +84,77 @@
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
<!-- 选择图片 -->
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManage" />
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManageRef" />
</el-dialog>
</div>
</template>
<script>
<script setup>
import { getCurrentInstance, nextTick, onMounted, ref } from "vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
name: "modelCarousel",
props: ["data"],
components: {
ossManage,
},
data() {
return {
showModal: false, // modal显隐
selected: null, // 已选数据
picModelFlag: false, // 选择图片modal
bgColor: "#fff", // 轮播背景色
};
},
mounted() {
this.bgColor = this.data.options.list[0].bgColor;
},
methods: {
handleSelectModel() {
// 编辑模块
this.showModal = true;
},
// 自动切换时改变背景色
autoChange(oVal, val) {
this.bgColor = this.data.options.list[val].bgColor;
},
// 添加轮播图片和链接
handleAdd() {
this.data.options.list.push({ img: "", url: "", bgColor: "#fff" });
this.$forceUpdate();
},
// 打开选择链接modal
handleSelectLink(item) {
this.$refs.liliDialog.open("link");
this.selected = item;
},
callbackSelected(item) {
// 选择图片回调
this.picModelFlag = false;
this.selected.img = item.url;
},
// 删除图片
handleDel(index) {
this.data.options.list.splice(index, 1);
},
selectedLink(val) {
// 选择链接回调
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
// 打开选择图片modal
handleSelectImg(item) {
this.selected = item;
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
},
};
import { formatLinkType } from "@/utils/filters";
defineOptions({ name: "modelCarousel" });
const props = defineProps(["data"]);
const { proxy } = getCurrentInstance();
const showModal = ref(false); // modal显隐
const selected = ref(null); // 已选数据
const picModelFlag = ref(false); // 选择图片modal
const bgColor = ref("#fff"); // 轮播背景色
const liliDialog = ref(null);
const ossManageRef = ref(null);
onMounted(() => {
bgColor.value = props.data.options.list[0].bgColor;
});
// 编辑模块
function handleSelectModel() {
showModal.value = true;
}
// 自动切换时改变背景色
function autoChange(oVal, val) {
bgColor.value = props.data.options.list[val].bgColor;
}
// 添加轮播图片和链接
function handleAdd() {
props.data.options.list.push({ img: "", url: "", bgColor: "#fff" });
proxy.$forceUpdate();
}
// 打开选择链接modal
function handleSelectLink(item) {
liliDialog.value.open("link");
selected.value = item;
}
// 选择图片回调
function callbackSelected(item) {
picModelFlag.value = false;
selected.value.img = item.url;
}
// 删除图片
function handleDel(index) {
props.data.options.list.splice(index, 1);
}
// 选择链接回调
function selectedLink(val) {
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
// 打开选择图片modal
function handleSelectImg(item) {
selected.value = item;
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
</script>
<style scoped lang="scss">

View File

@@ -204,88 +204,88 @@
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
<!-- 选择图片 -->
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManage" />
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManageRef" />
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, reactive, nextTick, getCurrentInstance } from "vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
name: "modelCarousel",
props: ["data"],
components: {
ossManage,
},
data() {
return {
showModal: false, // modal显隐
selected: null, // 已选数据
picModelFlag: false, // 选择图片modal
userInfo: {},
articleList: [
{ title: "促销计算规则" },
{ title: "商家申请开店" },
{ title: "商家账号注册" },
{ title: "促销计算规则" },
],
};
},
import { formatLinkType } from "@/utils/filters";
methods: {
handleSelectModel() {
// 编辑模块
this.showModal = true;
},
// 添加轮播
handleAdd() {
this.data.options.list.push({ img: "", url: "" });
this.$forceUpdate();
},
// 添加图片组
handleAddGroup() {
this.data.options.listRight.push([
{ img: "", url: "" },
{ img: "", url: "" },
{ img: "", url: "" },
]);
},
// 删除图片组
handleTabRemove(index) {
this.data.options.listRight.splice(index, 1);
},
// 打开图片链接
handleSelectLink(item) {
this.$refs.liliDialog.open("link");
this.selected = item;
},
callbackSelected(item) {
// 选择图片回调
this.picModelFlag = false;
this.selected.img = item.url;
},
// 删除图片
handleDel(index) {
this.data.options.list.splice(index, 1);
},
selectedLink(val) {
// 选择链接回调
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
// 打开选择图片modal
handleSelectImg(item) {
this.selected = item;
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
},
};
defineOptions({ name: "modelCarousel" });
const props = defineProps(["data"]);
const { proxy } = getCurrentInstance();
const showModal = ref(false); // modal显隐
const selected = ref(null); // 已选数据
const picModelFlag = ref(false); // 选择图片modal
const userInfo = reactive({});
const articleList = ref([
{ title: "促销计算规则" },
{ title: "商家申请开店" },
{ title: "商家账号注册" },
{ title: "促销计算规则" },
]);
const liliDialog = ref(null);
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const ossManageRef = ref(null);
function handleSelectModel() {
// 编辑模块
showModal.value = true;
}
// 添加轮播
function handleAdd() {
props.data.options.list.push({ img: "", url: "" });
proxy.$forceUpdate();
}
// 添加图片组
function handleAddGroup() {
props.data.options.listRight.push([
{ img: "", url: "" },
{ img: "", url: "" },
{ img: "", url: "" },
]);
}
// 删除图片组
function handleTabRemove(index) {
props.data.options.listRight.splice(index, 1);
}
// 打开图片链接
function handleSelectLink(item) {
liliDialog.value.open("link");
selected.value = item;
}
function callbackSelected(item) {
// 选择图片回调
picModelFlag.value = false;
selected.value.img = item.url;
}
// 删除图片
function handleDel(index) {
props.data.options.list.splice(index, 1);
}
function selectedLink(val) {
// 选择链接回调
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
// 打开选择图片modal
function handleSelectImg(item) {
selected.value = item;
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
</script>
<style scoped lang="scss">

View File

@@ -113,80 +113,80 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, nextTick } from "vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
props: {
data: {
type: Object,
default: null,
},
import { formatLinkType } from "@/utils/filters";
const props = defineProps({
data: {
type: Object,
default: null,
},
components: { ossManage },
data() {
return {
options: this.data.options, // 当前类型数据
showModal: false, // modal显隐
selected: {}, // 弹窗编辑草稿
editTarget: null, // 确定后写回的原数据
picModelFlag: false, // 图片选择器
};
},
methods: {
cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
},
// 打开装修modal
handleSelectModel(item, type) {
this.editTarget = item;
this.selected = this.cloneItem(item);
this.showModal = true;
},
handleSelectLink(item, index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
},
// 选择链接回调
selectedLink(val) {
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
handleSelectImg() {
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
// 选择图片回调
callbackSelected(val) {
this.picModelFlag = false;
if (!val?.url) return;
this.selected.img = val.url;
},
handleCancelModal() {
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleConfirmModal() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
},
};
});
const options = ref(props.data.options); // 当前类型数据
const showModal = ref(false); // modal显隐
const selected = ref({}); // 弹窗编辑草稿
const editTarget = ref(null); // 确定后写回的原数据
const picModelFlag = ref(false); // 图片选择器
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const liliDialog = ref(null);
const ossManageRef = ref(null);
function cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
}
// 打开装修modal
function handleSelectModel(item, type) {
editTarget.value = item;
selected.value = cloneItem(item);
showModal.value = true;
}
function handleSelectLink(item, index) {
// 调起选择链接弹窗
liliDialog.value.open("link");
}
// 选择链接回调
function selectedLink(val) {
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
function handleSelectImg() {
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
// 选择图片回调
function callbackSelected(val) {
picModelFlag.value = false;
if (!val?.url) return;
selected.value.img = val.url;
}
function handleCancelModal() {
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleConfirmModal() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
</script>
<style lang="scss" scoped>
@import "./setup-box.scss";

View File

@@ -158,7 +158,7 @@
<!-- 选择商品。链接 -->
<liliDialog
ref="liliDialog"
ref="liliDialogRef"
@selectedLink="selectedLink"
@selectedGoodsData="selectedGoodsData"
></liliDialog>
@@ -170,110 +170,104 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, nextTick } from "vue";
import { formatLinkType } from "@/utils/filters";
import ossManage from "@/views/sys/oss-manage/ossManage.vue";
export default {
name: "forYour",
data() {
return {
showModal: false,
defineOptions({ name: "forYour" });
picModelFlag: false,
selectedData: "", //选中的数据
goodsIndex: 0, // 商品索引
align: "",
defaultCallbackImageType: "",
current: "",
};
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
props: {
data: {
type: Object,
default: () => ({}),
},
},
components: {
ossManage,
},
mounted() {
},
methods: {
handleSelectImg(type, index) {
this.defaultCallbackImageType = type;
this.goodsIndex = index;
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
});
handleSelectGoods(val, index) {
this.$refs.liliDialog.open("goods");
this.$refs.liliDialog.singleGoods();
this.selectedData = val;
this.goodsIndex = index;
},
handleSelectLink(val, index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
this.selectedData = val;
const showModal = ref(false);
const picModelFlag = ref(false);
const selectedData = ref(""); //选中的数据
const goodsIndex = ref(0); // 商品索引
const align = ref("");
const defaultCallbackImageType = ref("");
const current = ref("");
this.goodsIndex = index;
},
// 回显图片
callbackSelected(val) {
this.picModelFlag = false;
if (this.defaultCallbackImageType == "image") {
this.data.options.data.image.src = val.url;
} else {
this.data.options.data[this.defaultCallbackImageType][
this.goodsIndex
].img = val.url;
}
},
// 选择商品回调
selectedGoodsData(val) {
this.data.options.data.hot.list[this.goodsIndex].img = val[0].thumbnail;
this.data.options.data.hot.list[this.goodsIndex].title = val[0].goodsName;
this.data.options.data.hot.list[this.goodsIndex].price = val[0].price;
this.data.options.data.hot.list[this.goodsIndex].url =
this.$filters.formatLinkType(val[0]);
const liliDialogRef = ref(null);
const ossManageRef = ref(null);
console.log(val, this.selectedData, this.goodsIndex);
},
// 选择链接回调
selectedLink(val) {
console.log(val,this.selectedData)
if (this.selectedData == "image") {
this.data.options.data.image.url =
this.$filters.formatLinkType(val);
} else {
console.log(this.data.options.data.list,this.goodsIndex)
this.data.options.data.list[
this.goodsIndex
].url = this.$filters.formatLinkType(val);
}
},
/*
* 点击不同模块进行编辑
* 判断也很简单,就是第一个第二个模块进行判断
*
* */
handleSelectModel() {
this.showModal = true;
},
},
};
function handleSelectImg(type, index) {
defaultCallbackImageType.value = type;
goodsIndex.value = index;
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
function handleSelectGoods(val, index) {
liliDialogRef.value.open("goods");
liliDialogRef.value.singleGoods();
selectedData.value = val;
goodsIndex.value = index;
}
function handleSelectLink(val, index) {
// 调起选择链接弹窗
liliDialogRef.value.open("link");
selectedData.value = val;
goodsIndex.value = index;
}
// 回显图片
function callbackSelected(val) {
picModelFlag.value = false;
if (defaultCallbackImageType.value == "image") {
props.data.options.data.image.src = val.url;
} else {
props.data.options.data[defaultCallbackImageType.value][
goodsIndex.value
].img = val.url;
}
}
// 选择商品回调
function selectedGoodsData(val) {
props.data.options.data.hot.list[goodsIndex.value].img = val[0].thumbnail;
props.data.options.data.hot.list[goodsIndex.value].title = val[0].goodsName;
props.data.options.data.hot.list[goodsIndex.value].price = val[0].price;
props.data.options.data.hot.list[goodsIndex.value].url =
formatLinkType(val[0]);
console.log(val, selectedData.value, goodsIndex.value);
}
// 选择链接回调
function selectedLink(val) {
console.log(val, selectedData.value)
if (selectedData.value == "image") {
props.data.options.data.image.url =
formatLinkType(val);
} else {
console.log(props.data.options.data.list, goodsIndex.value)
props.data.options.data.list[
goodsIndex.value
].url = formatLinkType(val);
}
}
/*
* 点击不同模块进行编辑
* 判断也很简单,就是第一个第二个模块进行判断
*
* */
function handleSelectModel() {
showModal.value = true;
}
</script>
<style scoped lang="scss">

View File

@@ -123,116 +123,118 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted } from "vue";
import { formatLinkType } from "@/utils/filters";
export default {
name: "goods",
defineOptions({ name: "goods" });
props: {
data: {
type: Object,
default: () => ({}),
},
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
data() {
return {
tabIndex:0,
current: 0,
showModal: false,
selected: {}, // 已选数据
picModelFlag: false,
tabCurrentlyIndex: 0, // 选项卡索引
};
},
mounted(){
this.tabIndex = this.data.options.labels[0].___index
},
methods: {
/**
* 算出最大的index 然后索引叠加
*/
handleTabsAdd() {
let findAllIndex = this.data.options.labels.map((item) => {
return item.___index;
});
let max = Math.max.apply(null, findAllIndex);
});
this.data.options.labels.push({
label: "标签" + (max + 1),
___index: max + 1,
});
},
// 删除标签
handleContextMenuDelete(item,index) {
// 删除标签下关联的商品
this.data.options.list.forEach((lab,currently)=>{
if(lab.___index == item.___index){
this.data.options.list.splice(currently,1)
}
})
// 删除当前标签
this.data.options.labels.splice(index,1)
},
// 删除商品
delGoods(val) {
this.data.options.list.forEach((item, i) => {
if (
item.title == val.title &&
item.___index == this.tabCurrentlyIndex
) {
this.data.options.list.splice(i, 1);
}
});
},
// 切换选项卡
handleClickTab(name) {
console.log(name)
this.tabCurrentlyIndex = name;
},
// 添加当前选项卡中的商品
addCurrentGoods() {
const liliDialog = ref(null);
this.$refs.liliDialog.clearGoodsSelected();
this.$refs.liliDialog.open("goods");
},
// 编辑模块
handleSelectModel(item) {
console.log(item);
this.selected = item;
this.showModal = true;
},
// 选择商品回调
selectedGoodsData(val) {
if (val.length) {
val.forEach((item) => {
const pushGoodsDetail = {
img: item.thumbnail,
price: item.price,
title: item.goodsName,
desc: "",
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
___index: this.tabCurrentlyIndex,
};
this.data.options.list.push(pushGoodsDetail);
});
}
},
// 选择链接回调
selectedLink(val) {
this.selected[this.current].url =
this.$filters.formatLinkType(val);
this.selected[this.current].type =
val.___type === "other" && val.url === "" ? "link" : "other";
const tabIndex = ref(0);
const current = ref(0);
const showModal = ref(false);
const selected = ref({}); // 已选数据
const picModelFlag = ref(false);
const tabCurrentlyIndex = ref(0); // 选项卡索引
console.log(this.selected[this.current]);
},
handleSelectLink(index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
this.current = index;
},
},
};
onMounted(() => {
tabIndex.value = props.data.options.labels[0].___index;
});
/**
* 算出最大的index 然后索引叠加
*/
function handleTabsAdd() {
let findAllIndex = props.data.options.labels.map((item) => {
return item.___index;
});
let max = Math.max.apply(null, findAllIndex);
props.data.options.labels.push({
label: "标签" + (max + 1),
___index: max + 1,
});
}
// 删除标签
function handleContextMenuDelete(item, index) {
// 删除标签下关联的商品
props.data.options.list.forEach((lab, currently) => {
if (lab.___index == item.___index) {
props.data.options.list.splice(currently, 1);
}
});
// 删除当前标签
props.data.options.labels.splice(index, 1);
}
// 删除商品
function delGoods(val) {
props.data.options.list.forEach((item, i) => {
if (item.title == val.title && item.___index == tabCurrentlyIndex.value) {
props.data.options.list.splice(i, 1);
}
});
}
// 切换选项卡
function handleClickTab(name) {
console.log(name);
tabCurrentlyIndex.value = name;
}
// 添加当前选项卡中的商品
function addCurrentGoods() {
liliDialog.value.clearGoodsSelected();
liliDialog.value.open("goods");
}
// 编辑模块
function handleSelectModel(item) {
console.log(item);
selected.value = item;
showModal.value = true;
}
// 选择商品回调
function selectedGoodsData(val) {
if (val.length) {
val.forEach((item) => {
const pushGoodsDetail = {
img: item.thumbnail,
price: item.price,
title: item.goodsName,
desc: "",
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
___index: tabCurrentlyIndex.value,
};
props.data.options.list.push(pushGoodsDetail);
});
}
}
// 选择链接回调
function selectedLink(val) {
selected.value[current.value].url = formatLinkType(val);
selected.value[current.value].type =
val.___type === "other" && val.url === "" ? "link" : "other";
console.log(selected.value[current.value]);
}
function handleSelectLink(index) {
// 调起选择链接弹窗
liliDialog.value.open("link");
current.value = index;
}
</script>
<style scoped lang="scss">

View File

@@ -154,120 +154,117 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { getCurrentInstance, nextTick, ref } from "vue";
import left from "./mixs/mix-goods";
import right from "./mixs/mix-brand";
import ossManage from "@/views/sys/oss-manage/ossManage.vue";
import { formatLinkType } from "@/utils/filters";
export default {
name: "mixModel",
data() {
return {
showModal: false,
current: "", //当前选择的模块
picModelFlag: false,
selectedData: "", //选中的数据
goodsIndex: 0, // 商品索引
align: "",
defaultCallbackImageType: "",
};
},
props: {
data: {
type: Object,
default: () => ({}),
},
},
components: {
left,
right,
ossManage,
},
mounted() {},
methods: {
handleSelectImg(type, index) {
this.defaultCallbackImageType = type;
this.goodsIndex = index;
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
defineOptions({ name: "mixModel" });
handleSelectGoods(val, index) {
this.$refs.liliDialog.open("goods");
this.$refs.liliDialog.singleGoods();
this.selectedData = val;
this.goodsIndex = index;
},
handleSelectLink(val, index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
this.selectedData = val;
this.goodsIndex = index;
},
// 回显图片
callbackSelected(val) {
this.picModelFlag = false;
if (this.defaultCallbackImageType == "default") {
console.log(this.current.data.image);
this.current.data.image.src = val.url;
} else {
console.log(this.goodsIndex, this.data.options[this.align].data.list);
this.data.options[this.align].data.list[this.goodsIndex].img = val.url;
// this.data.options[this.align].data[this.selectedData][this.goodsIndex].url = val.img
}
},
// 选择商品回调
selectedGoodsData(val) {
console.log(val);
this.$nextTick(() => {
this.data.options[this.align].data.list[this.goodsIndex].img =
val[0].thumbnail;
this.data.options[this.align].data.list[this.goodsIndex].title =
val[0].goodsName;
this.data.options[this.align].data.list[this.goodsIndex].price =
val[0].price;
this.data.options[this.align].data.list[this.goodsIndex].url =
val[0].url;
});
console.log(this.data.options[this.align].data.list[this.goodsIndex]);
this.$forceUpdate();
},
// 选择链接回调
selectedLink(val) {
if (this.selectedData != "list") {
this.data.options[this.align].data[this.selectedData].url = this.$filters.formatLinkType(val);
console.log(this.data.options[this.align].data[this.selectedData])
}
if (this.selectedData == "list") {
this.data.options[this.align].data[this.selectedData][this.goodsIndex]
.url = this.$filters.formatLinkType(val);
}
},
/*
* 点击不同模块进行编辑
* 判断也很简单,就是第一个第二个模块进行判断
*
* */
handleSelectModel(align) {
this.align = align;
this.current = this.data.options[align];
console.log(this.data.options[align]);
this.showModal = true;
},
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
};
});
const { proxy } = getCurrentInstance();
const showModal = ref(false);
const current = ref(""); //当前选择的模块
const picModelFlag = ref(false);
const selectedData = ref(""); //选中的数据
const goodsIndex = ref(0); // 商品索引
const align = ref("");
const defaultCallbackImageType = ref("");
const liliDialog = ref(null);
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const ossManageRef = ref(null);
function handleSelectImg(type, index) {
defaultCallbackImageType.value = type;
goodsIndex.value = index;
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
function handleSelectGoods(val, index) {
liliDialog.value.open("goods");
liliDialog.value.singleGoods();
selectedData.value = val;
goodsIndex.value = index;
}
function handleSelectLink(val, index) {
// 调起选择链接弹窗
liliDialog.value.open("link");
selectedData.value = val;
goodsIndex.value = index;
}
// 回显图片
function callbackSelected(val) {
picModelFlag.value = false;
if (defaultCallbackImageType.value == "default") {
console.log(current.value.data.image);
current.value.data.image.src = val.url;
} else {
console.log(goodsIndex.value, props.data.options[align.value].data.list);
props.data.options[align.value].data.list[goodsIndex.value].img = val.url;
// props.data.options[align.value].data[selectedData.value][goodsIndex.value].url = val.img
}
}
// 选择商品回调
function selectedGoodsData(val) {
console.log(val);
nextTick(() => {
props.data.options[align.value].data.list[goodsIndex.value].img =
val[0].thumbnail;
props.data.options[align.value].data.list[goodsIndex.value].title =
val[0].goodsName;
props.data.options[align.value].data.list[goodsIndex.value].price =
val[0].price;
props.data.options[align.value].data.list[goodsIndex.value].url =
val[0].url;
});
console.log(props.data.options[align.value].data.list[goodsIndex.value]);
proxy.$forceUpdate();
}
// 选择链接回调
function selectedLink(val) {
if (selectedData.value != "list") {
props.data.options[align.value].data[selectedData.value].url = formatLinkType(val);
console.log(props.data.options[align.value].data[selectedData.value])
}
if (selectedData.value == "list") {
props.data.options[align.value].data[selectedData.value][goodsIndex.value]
.url = formatLinkType(val);
}
}
/*
* 点击不同模块进行编辑
* 判断也很简单,就是第一个第二个模块进行判断
*
* */
function handleSelectModel(alignVal) {
align.value = alignVal;
current.value = props.data.options[alignVal];
console.log(props.data.options[alignVal]);
showModal.value = true;
}
</script>
<style scoped lang="scss">

View File

@@ -22,25 +22,17 @@
</div>
</template>
<script>
<script setup>
import { ArrowRight } from "@element-plus/icons-vue";
export default {
name: "mix-goods",
components: { ArrowRight },
data() {
return {}
},
props: {
data: {
type: Object,
default: () => ({})
}
},
mounted() {
},
methods: {}
}
defineOptions({ name: "mix-goods" });
defineProps({
data: {
type: Object,
default: () => ({})
}
});
</script>
<style scoped lang="scss">

View File

@@ -24,24 +24,15 @@
</div>
</template>
<script>
export default {
name: "mix-goods",
data() {
return {}
},
props: {
data: {
type: Object,
default: () => ({})
}
},
components: {},
mounted() {
<script setup>
defineOptions({ name: "mix-goods" });
},
methods: {}
}
defineProps({
data: {
type: Object,
default: () => ({})
}
});
</script>
<style scoped lang="scss">

View File

@@ -242,125 +242,123 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { nextTick, ref } from "vue";
import { formatLinkType } from "@/utils/filters";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
props: {
data: {
type: Object,
default: null,
},
const props = defineProps({
data: {
type: Object,
default: null,
},
components: {
ossManage,
},
data() {
return {
options: this.data.options, // 当前数据
showModal: false, // modal显隐
showModal1: false, // modal显隐
selected: {}, // 弹窗编辑草稿
editTarget: null, // 确定后写回的原数据
picModelFlag: false, // 选择图片modal
};
},
methods: {
cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
},
// 装修modal
handleSelectModel(item, type) {
this.editTarget = item;
this.selected = this.cloneItem(item);
if (type) {
this.showModal1 = true;
} else {
this.showModal = true;
}
},
handleSelectLink() {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
},
handleSelectGoods(item) {
if (item) {
this.editTarget = item;
this.selected = this.cloneItem(item);
}
this.$refs.liliDialog.open("goods", "single");
setTimeout(() => {
this.$refs.liliDialog.goodsData = [this.selected];
}, 500);
},
// 选择链接回调
selectedLink(val) {
if (!this.selected) return;
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
// 选择商品回调
selectedGoodsData(val) {
if (!val?.length || !this.selected) return;
const goods = val[0];
this.selected.img = goods.thumbnail;
this.selected.price = goods.price;
this.selected.name = goods.goodsName;
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
if (this.editTarget && !this.showModal && !this.showModal1) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
this.editTarget = null;
this.selected = {};
}
},
handleSelectImg() {
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
// 选择图片回显
callbackSelected(val) {
this.picModelFlag = false;
if (!val?.url) return;
this.selected.img = val.url;
},
handleCancelModal() {
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleConfirmModal() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleCancelModal1() {
this.editTarget = null;
this.selected = {};
this.showModal1 = false;
},
handleConfirmModal1() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal1 = false;
},
},
};
});
const options = ref(props.data.options); // 当前数据
const showModal = ref(false); // modal显隐
const showModal1 = ref(false); // modal显隐
const selected = ref({}); // 弹窗编辑草稿
const editTarget = ref(null); // 确定后写回的原数据
const picModelFlag = ref(false); // 选择图片modal
const liliDialog = ref(null);
// ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const ossManageRef = ref(null);
function cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
}
// 装修modal
function handleSelectModel(item, type) {
editTarget.value = item;
selected.value = cloneItem(item);
if (type) {
showModal1.value = true;
} else {
showModal.value = true;
}
}
function handleSelectLink() {
// 调起选择链接弹窗
liliDialog.value.open("link");
}
function handleSelectGoods(item) {
if (item) {
editTarget.value = item;
selected.value = cloneItem(item);
}
liliDialog.value.open("goods", "single");
setTimeout(() => {
liliDialog.value.goodsData = [selected.value];
}, 500);
}
// 选择链接回调
function selectedLink(val) {
if (!selected.value) return;
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
// 选择商品回调
function selectedGoodsData(val) {
if (!val?.length || !selected.value) return;
const goods = val[0];
selected.value.img = goods.thumbnail;
selected.value.price = goods.price;
selected.value.name = goods.goodsName;
selected.value.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
if (editTarget.value && !showModal.value && !showModal1.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
editTarget.value = null;
selected.value = {};
}
}
function handleSelectImg() {
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
// 选择图片回显
function callbackSelected(val) {
picModelFlag.value = false;
if (!val?.url) return;
selected.value.img = val.url;
}
function handleCancelModal() {
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleConfirmModal() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleCancelModal1() {
editTarget.value = null;
selected.value = {};
showModal1.value = false;
}
function handleConfirmModal1() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal1.value = false;
}
</script>
<style lang="scss" scoped>
@import "./setup-box.scss";

View File

@@ -96,118 +96,116 @@
></liliDialog>
</div>
</template>
<script>
export default {
props:{
data:{
type: Object,
default: null
}
},
data() {
return {
currentIndex:0,
conData:this.data,
selected:{},
editTarget: null,
showModal:false,
showGoodsModal: false,
showContent:true,
draftNavList: [],
draftGoodsList: [],
}
},
watch:{
data:function(val){
this.conData = val
},
conData:function(val){
this.$emit('content',val)
}
},
methods:{
cloneList(list) {
return JSON.parse(JSON.stringify(list || []));
},
cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
},
changeCurr(index){
this.currentIndex = index;
},
handleSelectModel () {
this.draftNavList = this.cloneList(this.conData.options.navList);
this.draftGoodsList = this.cloneList(this.conData.options.list);
this.showModal = true;
},
handleSelectGoods(item) {
this.editTarget = item;
this.selected = this.cloneItem(item);
this.showGoodsModal = true;
},
handleOpenGoodsPicker() {
this.$refs.liliDialog.open('goods', 'single');
setTimeout(() => {
this.$refs.liliDialog.goodsData = [this.selected];
}, 500);
},
selectedGoodsData(val){
if (!val?.length) return;
const goods = val[0];
this.selected.img = goods.thumbnail;
this.selected.price = goods.price;
this.selected.name = goods.goodsName;
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
},
handleDelNav(index){
this.draftNavList.splice(index,1);
this.draftGoodsList.splice(index,1);
},
handleAddNav(){
this.draftNavList.push({ title:'', desc:'' });
this.draftGoodsList.push([
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
]);
},
handleCancelModal() {
this.draftNavList = [];
this.draftGoodsList = [];
this.showModal = false;
},
handleConfirmModal() {
this.conData.options.navList = this.cloneList(this.draftNavList);
this.conData.options.list = this.cloneList(this.draftGoodsList);
this.draftNavList = [];
this.draftGoodsList = [];
this.showContent = false;
this.$nextTick(() => {
this.showContent = true;
});
this.showModal = false;
},
handleCancelGoodsModal() {
this.editTarget = null;
this.selected = {};
this.showGoodsModal = false;
},
handleConfirmGoodsModal() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showGoodsModal = false;
},
<script setup>
import { nextTick, ref, watch } from "vue";
const props = defineProps({
data:{
type: Object,
default: null
}
});
const emit = defineEmits(['content']);
const currentIndex = ref(0);
const conData = ref(props.data);
const selected = ref({});
const editTarget = ref(null);
const showModal = ref(false);
const showGoodsModal = ref(false);
const showContent = ref(true);
const draftNavList = ref([]);
const draftGoodsList = ref([]);
const liliDialog = ref(null);
watch(() => props.data, (val) => {
conData.value = val;
});
watch(conData, (val) => {
emit('content', val);
});
function cloneList(list) {
return JSON.parse(JSON.stringify(list || []));
}
function cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
}
function changeCurr(index){
currentIndex.value = index;
}
function handleSelectModel () {
draftNavList.value = cloneList(conData.value.options.navList);
draftGoodsList.value = cloneList(conData.value.options.list);
showModal.value = true;
}
function handleSelectGoods(item) {
editTarget.value = item;
selected.value = cloneItem(item);
showGoodsModal.value = true;
}
function handleOpenGoodsPicker() {
liliDialog.value.open('goods', 'single');
setTimeout(() => {
liliDialog.value.goodsData = [selected.value];
}, 500);
}
function selectedGoodsData(val){
if (!val?.length) return;
const goods = val[0];
selected.value.img = goods.thumbnail;
selected.value.price = goods.price;
selected.value.name = goods.goodsName;
selected.value.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
}
function handleDelNav(index){
draftNavList.value.splice(index,1);
draftGoodsList.value.splice(index,1);
}
function handleAddNav(){
draftNavList.value.push({ title:'', desc:'' });
draftGoodsList.value.push([
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
{ img:'', name:'', price:0, url:'' },
]);
}
function handleCancelModal() {
draftNavList.value = [];
draftGoodsList.value = [];
showModal.value = false;
}
function handleConfirmModal() {
conData.value.options.navList = cloneList(draftNavList.value);
conData.value.options.list = cloneList(draftGoodsList.value);
draftNavList.value = [];
draftGoodsList.value = [];
showContent.value = false;
nextTick(() => {
showContent.value = true;
});
showModal.value = false;
}
function handleCancelGoodsModal() {
editTarget.value = null;
selected.value = {};
showGoodsModal.value = false;
}
function handleConfirmGoodsModal() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showGoodsModal.value = false;
}
</script>
<style lang="scss" scoped>

View File

@@ -45,7 +45,7 @@
</el-dialog>
<!-- 选择商品。链接 -->
<liliDialog
ref="liliDialog"
ref="liliDialogRef"
@selectedLink="selectedLink"
@selectedGoodsData="selectedGoodsData"
></liliDialog>
@@ -56,75 +56,80 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { nextTick, ref } from "vue";
import { formatLinkType } from "@/utils/filters";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
name: "oneRowThreeColumns",
components:{ossManage},
props: {
data: {
type: Object,
default: () => ({})
}
},
data () {
return {
showModal:false,
selected: {}, // 已选数据
picModelFlag:false,
current:0,
};
},
methods: {
// 回显图片
callbackSelected(val) {
this.picModelFlag = false;
this.selected[this.current].img = val.url;
console.log(this.selected)
},
// 编辑模块
handleSelectModel(item) {
this.selected = item;
this.showModal = true;
},
// 选择商品回调
selectedGoodsData(val) {
console.log(val);
let goods = val[0];
this.selected.img = goods.thumbnail;
this.selected.price = goods.price;
this.selected.name = goods.goodsName;
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
},
// 选择链接回调
selectedLink(val) {
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
handleSelectLink(index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
this.current = index;
},
handleSelectImg(index){
// 选择图片
this.current = index;
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
}
defineOptions({ name: "oneRowThreeColumns" });
defineProps({
data: {
type: Object,
default: () => ({})
}
});
const showModal = ref(false);
const selected = ref({}); // 已选数据
const picModelFlag = ref(false);
const current = ref(0);
const liliDialogRef = ref(null);
const ossManageRef = ref(null);
// 回显图片
function callbackSelected(val) {
picModelFlag.value = false;
selected.value[current.value].img = val.url;
console.log(selected.value)
}
// 编辑模块
function handleSelectModel(item) {
selected.value = item;
showModal.value = true;
}
// 选择商品回调
function selectedGoodsData(val) {
console.log(val);
let goods = val[0];
selected.value.img = goods.thumbnail;
selected.value.price = goods.price;
selected.value.name = goods.goodsName;
selected.value.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
}
// 选择链接回调
function selectedLink(val) {
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
function handleSelectLink(index) {
// 调起选择链接弹窗
liliDialogRef.value.open("link");
current.value = index;
}
function handleSelectImg(index) {
// 选择图片
current.value = index;
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
</script>

View File

@@ -76,75 +76,70 @@
</div>
</template>
<script>
<script setup>
import { ref } from "vue";
import { formatLinkType } from "@/utils/filters";
export default {
name: "onlyGoodsList",
props: {
data: {
type: Object,
default: () => ({}),
},
},
data() {
return {
flag:false,
tabIndex:0,
current: 0,
showModal: false,
selected: {}, // 已选数据
picModelFlag: false,
};
},
mounted(){
defineOptions({ name: "onlyGoodsList" });
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
methods: {
// 删除商品
delGoods(val,i) {
this.data.options.list.splice(i, 1);
},
// 添加当前选项卡中的商品
addCurrentGoods() {
this.$refs.liliDialog.open("goods");
},
// 编辑模块
handleSelectModel(item) {
console.log(item);
this.selected = item;
this.showModal = true;
},
// 选择商品回调
selectedGoodsData(val) {
if (val.length) {
val.forEach((item) => {
const pushGoodsDetail = {
img: item.thumbnail,
price: item.price,
title: item.goodsName,
desc: "",
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
};
this.data.options.list.push(pushGoodsDetail);
});
}
},
// 选择链接回调
selectedLink(val) {
this.selected[this.current].url =
this.$filters.formatLinkType(val);
this.selected[this.current].type =
val.___type === "other" && val.url === "" ? "link" : "other";
});
console.log(this.selected[this.current]);
},
handleSelectLink(index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
this.current = index;
},
},
};
const flag = ref(false);
const tabIndex = ref(0);
const current = ref(0);
const showModal = ref(false);
const selected = ref({}); // 已选数据
const picModelFlag = ref(false);
const liliDialog = ref(null);
// 删除商品
function delGoods(val, i) {
props.data.options.list.splice(i, 1);
}
// 添加当前选项卡中的商品
function addCurrentGoods() {
liliDialog.value.open("goods");
}
// 编辑模块
function handleSelectModel(item) {
console.log(item);
selected.value = item;
showModal.value = true;
}
// 选择商品回调
function selectedGoodsData(val) {
if (val.length) {
val.forEach((item) => {
const pushGoodsDetail = {
img: item.thumbnail,
price: item.price,
title: item.goodsName,
desc: "",
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
};
props.data.options.list.push(pushGoodsDetail);
});
}
}
// 选择链接回调
function selectedLink(val) {
selected.value[current.value].url = formatLinkType(val);
selected.value[current.value].type =
val.___type === "other" && val.url === "" ? "link" : "other";
console.log(selected.value[current.value]);
}
function handleSelectLink(index) {
// 调起选择链接弹窗
liliDialog.value.open("link");
current.value = index;
}
</script>
<style scoped lang="scss">

View File

@@ -216,7 +216,7 @@
</el-dialog>
<!-- 选择商品。链接 -->
<liliDialog
ref="liliDialog"
ref="liliDialogRef"
@selectedLink="selectedLink"
@selectedGoodsData="selectedGoodsData"
></liliDialog>
@@ -227,114 +227,111 @@
:is-component="true"
:initialize="picModelFlag"
:max-select="1"
ref="ossManage"
ref="ossManageRef"
/>
</el-dialog>
</div>
</template>
<script>
<script setup>
import { nextTick, reactive, ref } from "vue";
import ossManage from "@/views/sys/oss-manage/ossManage";
export default {
props: {
data: {
type: Object,
default: () => ({}),
},
import { formatLinkType } from "@/utils/filters";
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
components: {
ossManage,
},
data() {
return {
msgLeft: this.data.options.contentLeft, // 左侧数据
msgRight: this.data.options.contentRight, // 右侧数据
showModal: false, // modal显隐
showModal1: false, // modal显隐
selected: {}, // 弹窗编辑草稿
editTarget: null, // 确定后写回的原数据
picModelFlag: false, // 图片选择
};
},
methods: {
cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
},
// 编辑
handleSelectModel(item, type) {
this.editTarget = item;
this.selected = this.cloneItem(item);
if (type) {
this.showModal1 = true;
} else {
this.showModal = true;
}
},
handleSelectLink(item, index) {
// 调起选择链接弹窗
this.$refs.liliDialog.open("link");
},
handleSelectGoods(item) {
// 调起选择商品
this.$refs.liliDialog.open("goods", "single");
},
// 选择链接回调
selectedLink(val) {
this.selected.url = this.$filters.formatLinkType(val);
this.selected.type =
val.___type === "other" && val.url === "" ? "link" : "other";
},
// 选择商品回调
selectedGoodsData(val) {
console.log(val);
let goods = val[0];
this.selected.img = goods.thumbnail;
this.selected.price = goods.price;
this.selected.name = goods.goodsName;
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
},
handleSelectImg() {
// 选择图片
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
// 选择图片回调
callbackSelected(val) {
this.picModelFlag = false;
if (!val?.url) return;
this.selected.img = val.url;
},
handleCancelModal() {
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleConfirmModal() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal = false;
},
handleCancelModal1() {
this.editTarget = null;
this.selected = {};
this.showModal1 = false;
},
handleConfirmModal1() {
if (this.editTarget) {
Object.assign(this.editTarget, this.cloneItem(this.selected));
}
this.editTarget = null;
this.selected = {};
this.showModal1 = false;
},
},
};
});
const msgLeft = reactive(props.data.options.contentLeft); // 左侧数据
const msgRight = reactive(props.data.options.contentRight); // 右侧数据
const showModal = ref(false); // modal显隐
const showModal1 = ref(false); // modal显隐
const selected = ref({}); // 弹窗编辑草稿
const editTarget = ref(null); // 确定后写回的原数据
const picModelFlag = ref(false); // 图片选择
const liliDialogRef = ref(null);
const ossManageRef = ref(null);
function cloneItem(item) {
return JSON.parse(JSON.stringify(item || {}));
}
// 编辑
function handleSelectModel(item, type) {
editTarget.value = item;
selected.value = cloneItem(item);
if (type) {
showModal1.value = true;
} else {
showModal.value = true;
}
}
function handleSelectLink(item, index) {
// 调起选择链接弹窗
liliDialogRef.value.open("link");
}
function handleSelectGoods(item) {
// 调起选择商品
liliDialogRef.value.open("goods", "single");
}
// 选择链接回调
function selectedLink(val) {
selected.value.url = formatLinkType(val);
selected.value.type =
val.___type === "other" && val.url === "" ? "link" : "other";
}
// 选择商品回调
function selectedGoodsData(val) {
console.log(val);
let goods = val[0];
selected.value.img = goods.thumbnail;
selected.value.price = goods.price;
selected.value.name = goods.goodsName;
selected.value.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
}
function handleSelectImg() {
// 选择图片
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
// 选择图片回调
function callbackSelected(val) {
picModelFlag.value = false;
if (!val?.url) return;
selected.value.img = val.url;
}
function handleCancelModal() {
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleConfirmModal() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal.value = false;
}
function handleCancelModal1() {
editTarget.value = null;
selected.value = {};
showModal1.value = false;
}
function handleConfirmModal1() {
if (editTarget.value) {
Object.assign(editTarget.value, cloneItem(selected.value));
}
editTarget.value = null;
selected.value = {};
showModal1.value = false;
}
</script>
<style lang="scss" scoped>
@import "./setup-box.scss";

View File

@@ -37,121 +37,119 @@
</div>
</div>
</template>
<script>
<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import Swiper from "swiper";
import "swiper/swiper-bundle.css";
export default {
props: {
data: {
type: Object,
default: null,
},
},
data() {
return {
options: this.data.options, // 当前数据
actStatus: 0, // 0 未开始 1 进行中 2 已结束
actName: "限时秒杀",
currHour: "00", // 当前秒杀场
diffSeconds: 0, // 倒地时
hours: "00", // 小时
minutes: "00", // 分钟
seconds: "00", // 秒
interval: undefined, // 定时器
swiperInstance: null,
};
},
watch: {
diffSeconds(val) {
const hours = Math.floor(val / 3600);
// 当前秒数 / 60,向下取整
// 获取到所有分钟数 3600 / 60 = 60分钟
// 对60取模,超过小时数的分钟数
const minutes = Math.floor(val / 60) % 60;
// 当前的秒数 % 60,获取到 超过小时数、分钟数的秒数(秒数)
const seconds = val % 60;
this.hours = hours < 10 ? "0" + hours : hours;
this.minutes = minutes < 10 ? "0" + minutes : minutes;
this.seconds = seconds < 10 ? "0" + seconds : seconds;
if (val === 0) {
clearInterval(this.interval);
this.hours = 0;
this.minutes = 0;
this.seconds = 0;
this.countDown(this.options.list);
const props = defineProps({
data: {
type: Object,
default: null,
},
});
const options = ref(props.data.options); // 当前数据
const actStatus = ref(0); // 0 未开始 1 进行中 2 已结束
const actName = ref("限时秒杀");
const currHour = ref("00"); // 当前秒杀场
const diffSeconds = ref(0); // 倒地时
const hours = ref("00"); // 小时
const minutes = ref("00"); // 分钟
const seconds = ref("00"); // 秒
const interval = ref(undefined); // 定时器
const swiperInstance = ref(null);
const swiperEl = ref(null);
watch(diffSeconds, (val) => {
const h = Math.floor(val / 3600);
// 当前秒数 / 60,向下取整
// 获取到所有分钟数 3600 / 60 = 60分钟
// 对60取模,超过小时数的分钟数
const m = Math.floor(val / 60) % 60;
// 当前的秒数 % 60,获取到 超过小时数、分钟数的秒数(秒数)
const s = val % 60;
hours.value = h < 10 ? "0" + h : h;
minutes.value = m < 10 ? "0" + m : m;
seconds.value = s < 10 ? "0" + s : s;
if (val === 0) {
clearInterval(interval.value);
hours.value = 0;
minutes.value = 0;
seconds.value = 0;
countDown(options.value.list);
}
});
onMounted(() => {
countDown(options.value.list);
initSwiper();
});
onBeforeUnmount(() => {
clearInterval(interval.value);
if (swiperInstance.value) {
swiperInstance.value.destroy(true, true);
swiperInstance.value = null;
}
});
function initSwiper() {
if (!swiperEl.value) {
return;
}
swiperInstance.value = new Swiper(swiperEl.value, {
slidesPerView: 5,
autoplay: true,
loop: true,
});
}
// 倒计时
function countDown(list) {
/**
* 默认倒计时两小时
* 如果没有开始,则显示未开始
* 进行中显示倒计时
* 今天的秒杀结束则显示已结束
*/
let nowHour = new Date().getHours();
if (nowHour < Number(list[0].time)) {
// 活动未开始
currHour.value = list[0].time;
actStatus.value = 0;
} else if (nowHour >= Number(list[list.length - 1].time + 2)) {
// 活动已结束
actStatus.value = 2;
currHour.value = list[list.length - 1].time;
} else {
// 活动进行中
actStatus.value = 1;
for (let i = 0; i < list.length; i++) {
if (nowHour == Number(list[i].time)) {
currHour.value = list[i].time;
}
if (
nowHour > Number(list[i].time) &&
nowHour < Number(list[i].time + 2)
) {
currHour.value = list[i].time;
}
},
},
mounted() {
this.countDown(this.options.list);
this.initSwiper();
},
beforeUnmount() {
clearInterval(this.interval);
if (this.swiperInstance) {
this.swiperInstance.destroy(true, true);
this.swiperInstance = null;
}
},
methods: {
initSwiper() {
if (!this.$refs.swiperEl) {
return;
}
this.swiperInstance = new Swiper(this.$refs.swiperEl, {
slidesPerView: 5,
autoplay: true,
loop: true,
});
},
// 倒计时
countDown(list) {
/**
* 默认倒计时两小时
* 如果没有开始,则显示未开始
* 进行中显示倒计时
* 今天的秒杀结束则显示已结束
*/
let nowHour = new Date().getHours();
if (nowHour < Number(list[0].time)) {
// 活动未开始
this.currHour = list[0].time;
this.actStatus = 0;
} else if (nowHour >= Number(list[list.length - 1].time + 2)) {
// 活动已结束
this.actStatus = 2;
this.currHour = list[list.length - 1].time;
} else {
// 活动进行中
this.actStatus = 1;
for (let i = 0; i < list.length; i++) {
if (nowHour == Number(list[i].time)) {
this.currHour = list[i].time;
}
if (
nowHour > Number(list[i].time) &&
nowHour < Number(list[i].time + 2)
) {
this.currHour = list[i].time;
}
}
// 当前0点时间戳
let zeroTime = new Date(new Date().toLocaleDateString()).getTime();
// 活动倒计时
this.diffSeconds = Math.floor(
(zeroTime +
3600 * 1000 * (this.currHour + 2) -
new Date().getTime()) /
1000
);
this.interval = setInterval(() => {
this.diffSeconds--;
}, 1000);
}
},
},
};
// 当前0点时间戳
let zeroTime = new Date(new Date().toLocaleDateString()).getTime();
// 活动倒计时
diffSeconds.value = Math.floor(
(zeroTime +
3600 * 1000 * (currHour.value + 2) -
new Date().getTime()) /
1000
);
interval.value = setInterval(() => {
diffSeconds.value--;
}, 1000);
}
}
</script>
<style lang="scss" scoped>
.seckill {

View File

@@ -39,87 +39,84 @@
</div>
</div>
</template>
<script>
export default {
props: {
data: {
type: Object,
default: null,
},
},
data() {
return {
options: this.data.options,
actStatus: 0,
actName: "限时秒杀",
currHour: "00",
diffSeconds: 0,
hours: "00",
minutes: "00",
seconds: "00",
interval: undefined,
};
},
watch: {
diffSeconds(val) {
const hours = Math.floor(val / 3600);
const minutes = Math.floor(val / 60) % 60;
const seconds = val % 60;
this.hours = hours < 10 ? "0" + hours : hours;
this.minutes = minutes < 10 ? "0" + minutes : minutes;
this.seconds = seconds < 10 ? "0" + seconds : seconds;
<script setup>
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
if (val === 0) {
clearInterval(this.interval);
this.hours = 0;
this.minutes = 0;
this.seconds = 0;
this.countDown(this.options.list);
const props = defineProps({
data: {
type: Object,
default: null,
},
});
const options = ref(props.data.options);
const actStatus = ref(0);
const actName = ref("限时秒杀");
const currHour = ref("00");
const diffSeconds = ref(0);
const hours = ref("00");
const minutes = ref("00");
const seconds = ref("00");
let interval = undefined;
watch(diffSeconds, (val) => {
const h = Math.floor(val / 3600);
const m = Math.floor(val / 60) % 60;
const s = val % 60;
hours.value = h < 10 ? "0" + h : h;
minutes.value = m < 10 ? "0" + m : m;
seconds.value = s < 10 ? "0" + s : s;
if (val === 0) {
clearInterval(interval);
hours.value = 0;
minutes.value = 0;
seconds.value = 0;
countDown(options.value.list);
}
});
onMounted(() => {
countDown(options.value.list);
});
onBeforeUnmount(() => {
clearInterval(interval);
});
function countDown(list) {
const nowHour = new Date().getHours();
if (nowHour < Number(list[0].time)) {
currHour.value = list[0].time;
actStatus.value = 0;
} else if (nowHour >= Number(list[list.length - 1].time + 2)) {
actStatus.value = 2;
currHour.value = list[list.length - 1].time;
} else {
actStatus.value = 1;
for (let i = 0; i < list.length; i++) {
if (nowHour == Number(list[i].time)) {
currHour.value = list[i].time;
}
},
},
mounted() {
this.countDown(this.options.list);
},
beforeUnmount() {
clearInterval(this.interval);
},
methods: {
countDown(list) {
const nowHour = new Date().getHours();
if (nowHour < Number(list[0].time)) {
this.currHour = list[0].time;
this.actStatus = 0;
} else if (nowHour >= Number(list[list.length - 1].time + 2)) {
this.actStatus = 2;
this.currHour = list[list.length - 1].time;
} else {
this.actStatus = 1;
for (let i = 0; i < list.length; i++) {
if (nowHour == Number(list[i].time)) {
this.currHour = list[i].time;
}
if (
nowHour > Number(list[i].time) &&
nowHour < Number(list[i].time + 2)
) {
this.currHour = list[i].time;
}
}
const zeroTime = new Date(new Date().toLocaleDateString()).getTime();
this.diffSeconds = Math.floor(
(zeroTime +
3600 * 1000 * (this.currHour + 2) -
new Date().getTime()) /
1000
);
this.interval = setInterval(() => {
this.diffSeconds--;
}, 1000);
if (
nowHour > Number(list[i].time) &&
nowHour < Number(list[i].time + 2)
) {
currHour.value = list[i].time;
}
},
},
};
}
const zeroTime = new Date(new Date().toLocaleDateString()).getTime();
diffSeconds.value = Math.floor(
(zeroTime +
3600 * 1000 * (currHour.value + 2) -
new Date().getTime()) /
1000
);
interval = setInterval(() => {
diffSeconds.value--;
}, 1000);
}
}
</script>
<style lang="scss" scoped>
.seckill-wrap {

View File

@@ -28,143 +28,136 @@
</draggable>
</div>
<div class="show-content">
<model-form ref="modelForm" :data="modelForm"></model-form>
<model-form ref="modelFormRef" :data="modelForm"></model-form>
</div>
</div>
</div>
</template>
<script>
<script setup>
import { ref, onMounted, watch } from "vue";
import { useRoute } from "vue-router";
import { Picture } from "@element-plus/icons-vue";
import { modelData } from "./modelConfig";
import Draggable from "vuedraggable";
import ModelForm from "./modelForm.vue";
import * as API_floor from "@/api/other.js";
export default {
components: {
Draggable,
ModelForm,
Picture,
},
mounted() {
const cache = this.getStore('managerPCPageCache')
this.hasCache = !!cache;
if(cache){
this.$Modal.confirm({
title: '提示',
content: '获取到本地有缓存数据,是否使用缓存数据?',
okText: '使用',
cancelText: '取消',
onOk: () => {
this.applyPageData(cache);
}
});
import { getStore, setStore } from "@/libs/storage";
import { Message, Modal } from "@/utils/message";
const route = useRoute();
const hasCache = ref(false);
const modelForm = ref({ list: [] });
const submitLoading = ref(false);
const modelFormRef = ref(null);
onMounted(() => {
const cache = getStore('managerPCPageCache')
hasCache.value = !!cache;
if(cache){
Modal.confirm({
title: '提示',
content: '获取到本地有缓存数据,是否使用缓存数据?',
okText: '使用',
cancelText: '取消',
onOk: () => {
applyPageData(cache);
}
});
}
getTemplateItem(route.query.id);
});
function getModelKey(model) {
return model.type || model.name;
}
function cloneModel(model) {
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
const cloned = JSON.parse(JSON.stringify(model));
return {
...cloned,
key,
model: cloned.type + "_" + key,
};
}
function clearCache(){
setStore('managerPCPageCache', '')
Message.success('清除成功')
}
function witeLocalStore(){
const data ={...modelForm.value}
data.list.unshift(modelFormRef.value.navList);
data.list.unshift(modelFormRef.value.topAdvert);
setStore('managerPCPageCache', data)
Message.success('写入成功')
}
function saveTemplate() {
submitTemplate(route.query.pageShow ? 'OPEN' : 'CLOSE')
}
function submitTemplate(pageShow) {
submitLoading.value = true
const modelFormData = JSON.parse(JSON.stringify(modelForm.value))
modelFormData.list.unshift(modelFormRef.value.navList);
modelFormData.list.unshift(modelFormRef.value.topAdvert);
const data = {
id: route.query.id,
pageData: JSON.stringify(modelFormData),
pageShow: route.query.pageType === 'SPECIAL' ? 'CLOSE' : pageShow,
pageClientType: 'PC',
};
API_floor.updateHome(route.query.id, data).then((res) => {
submitLoading.value = false
if (res.success) {
Message.success("保存模板成功");
}
this.getTemplateItem(this.$route.query.id);
},
data() {
return {
hasCache:false,
modelData,
modelForm: { list: [] },
submitLoading: false,
};
},
methods: {
getModelKey(model) {
return model.type || model.name;
},
cloneModel(model) {
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
const cloned = JSON.parse(JSON.stringify(model));
return {
...cloned,
key,
model: cloned.type + "_" + key,
};
},
clearCache(){
this.setStore('managerPCPageCache', '')
this.$Message.success('清除成功')
},
witeLocalStore(){
const data ={...this.modelForm}
data.list.unshift(this.$refs.modelForm.navList);
data.list.unshift(this.$refs.modelForm.topAdvert);
this.setStore('managerPCPageCache', data)
this.$Message.success('写入成功')
},
saveTemplate() {
this.submitTemplate(this.$route.query.pageShow ? 'OPEN' : 'CLOSE')
},
submitTemplate(pageShow) {
this.submitLoading = true
const modelForm = JSON.parse(JSON.stringify(this.modelForm))
modelForm.list.unshift(this.$refs.modelForm.navList);
modelForm.list.unshift(this.$refs.modelForm.topAdvert);
const data = {
id: this.$route.query.id,
pageData: JSON.stringify(modelForm),
pageShow: this.$route.query.pageType === 'SPECIAL' ? 'CLOSE' : pageShow,
pageClientType: 'PC',
};
API_floor.updateHome(this.$route.query.id, data).then((res) => {
this.submitLoading = false
if (res.success) {
this.$Message.success("保存模板成功");
}
});
},
resetTemplate() {
this.getTemplateItem(this.$route.query.id);
},
applyPageData(raw) {
const empty = { list: [] };
if (raw == null || raw === "") {
this.modelForm = empty;
return;
}
let pageData = raw;
if (typeof raw === "string") {
try {
pageData = JSON.parse(raw);
} catch {
this.modelForm = empty;
return;
}
}
const list = Array.isArray(pageData)
? pageData
: Array.isArray(pageData?.list)
? pageData.list
: [];
const form = Array.isArray(pageData) ? { list } : { ...pageData, list };
if (list[0]?.type === "topAdvert") {
this.$refs.modelForm.topAdvert = list[0];
if (list[1]) {
this.$refs.modelForm.navList = list[1];
}
this.modelForm = { ...form, list: list.slice(2) };
return;
}
this.modelForm = { ...form, list };
},
getTemplateItem(id) {
API_floor.getHomeData(id).then((res) => {
if (res.success) {
this.applyPageData(res.result?.pageData);
}
});
},
},
watch: {
modelForm: {
deep: true,
handler: function (val) {
console.log(val);
},
},
},
};
});
}
function resetTemplate() {
getTemplateItem(route.query.id);
}
function applyPageData(raw) {
const empty = { list: [] };
if (raw == null || raw === "") {
modelForm.value = empty;
return;
}
let pageData = raw;
if (typeof raw === "string") {
try {
pageData = JSON.parse(raw);
} catch {
modelForm.value = empty;
return;
}
}
const list = Array.isArray(pageData)
? pageData
: Array.isArray(pageData?.list)
? pageData.list
: [];
const form = Array.isArray(pageData) ? { list } : { ...pageData, list };
if (list[0]?.type === "topAdvert") {
modelFormRef.value.topAdvert = list[0];
if (list[1]) {
modelFormRef.value.navList = list[1];
}
modelForm.value = { ...form, list: list.slice(2) };
return;
}
modelForm.value = { ...form, list };
}
function getTemplateItem(id) {
API_floor.getHomeData(id).then((res) => {
if (res.success) {
applyPageData(res.result?.pageData);
}
});
}
watch(modelForm, function (val) {
console.log(val);
}, { deep: true });
</script>
<style lang="scss" scoped>
.renovation {

View File

@@ -79,137 +79,136 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref, watch } from "vue";
import * as API_Shop from "@/api/shops";
import { Message, Modal } from "@/utils/message";
export default {
name: "logistics",
data() {
return {
row: {},
openModal: false,
loading: true,
searchForm: {
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
},
openModalTitle: "开启信息",
ruleValidate: {},
faceSheetForm: {
faceSheetFlag: false,
customerName: "",
payType: "1",
expType: "1",
customerPwd: "",
monthCode: "",
sendSite: "",
sendStaff: "",
},
data: [],
openText: false,
logisticsId: "",
};
},
watch: {
"faceSheetForm.faceSheetFlag"(val) {
this.openText = !!val;
},
},
methods: {
init() {
this.getDataList();
},
getDataList() {
this.loading = true;
API_Shop.getLogistics().then((res) => {
this.loading = false;
defineOptions({ name: "logistics" });
const row = ref({});
const openModal = ref(false);
const loading = ref(true);
const searchForm = ref({
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc",
});
const openModalTitle = ref("开启信息");
const ruleValidate = ref({});
const faceSheetForm = ref({
faceSheetFlag: false,
customerName: "",
payType: "1",
expType: "1",
customerPwd: "",
monthCode: "",
sendSite: "",
sendStaff: "",
});
const data = ref([]);
const openText = ref(false);
const logisticsId = ref("");
watch(
() => faceSheetForm.value.faceSheetFlag,
(val) => {
openText.value = !!val;
}
);
function init() {
getDataList();
}
function getDataList() {
loading.value = true;
API_Shop.getLogistics().then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result;
}
});
}
function open(v) {
row.value = v;
openModal.value = true;
openModalTitle.value = "开启信息";
openText.value = false;
faceSheetForm.value.faceSheetFlag = false;
}
function getFaceSheetInfo(v) {
row.value = v;
logisticsId.value = v.logisticsId;
openModalTitle.value = "修改信息";
API_Shop.getIsCheck(logisticsId.value).then((res) => {
if (res.success) {
faceSheetForm.value.faceSheetFlag = res.result.faceSheetFlag;
openText.value = !!faceSheetForm.value.faceSheetFlag;
faceSheetForm.value.customerName = res.result.customerName;
faceSheetForm.value.customerPwd = res.result.customerPwd;
faceSheetForm.value.monthCode = res.result.monthCode;
faceSheetForm.value.sendSite = res.result.sendSite;
faceSheetForm.value.sendStaff = res.result.sendStaff;
faceSheetForm.value.payType = res.result.payType;
faceSheetForm.value.expType = res.result.expType;
}
});
openModal.value = true;
}
function frontDownload(val) {
const a = document.createElement("a");
if (val === "use") {
a.href = "static/instructions.xlsx";
a.download = "使用说明.xlsx";
} else if (val === "type") {
a.href = "static/logisticsType.xlsx";
a.download = "快递类型.xlsx";
}
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
}
function submit() {
if (!row.value.selected) {
API_Shop.logisticsChecked(row.value.logisticsId, faceSheetForm.value).then((res) => {
openModal.value = false;
if (res.success) {
Message.success("物流公司开启成功");
init();
}
});
} else {
API_Shop.editChecked(logisticsId.value, faceSheetForm.value).then((res) => {
if (res.success) {
Message.success("修改成功");
openModal.value = false;
init();
}
});
}
}
function close(v) {
Modal.confirm({
title: "确认关闭",
content: "您确认关闭此物流公司?",
loading: true,
onOk: () => {
API_Shop.logisticsUnChecked(v.logisticsId).then((res) => {
Modal.remove();
if (res.success) {
this.data = res.result;
Message.success("物流公司关闭成功");
init();
}
});
},
open(v) {
this.row = v;
this.openModal = true;
this.openModalTitle = "开启信息";
this.openText = false;
this.faceSheetForm.faceSheetFlag = false;
},
getFaceSheetInfo(v) {
this.row = v;
this.logisticsId = v.logisticsId;
this.openModalTitle = "修改信息";
API_Shop.getIsCheck(this.logisticsId).then((res) => {
if (res.success) {
this.faceSheetForm.faceSheetFlag = res.result.faceSheetFlag;
this.openText = !!this.faceSheetForm.faceSheetFlag;
this.faceSheetForm.customerName = res.result.customerName;
this.faceSheetForm.customerPwd = res.result.customerPwd;
this.faceSheetForm.monthCode = res.result.monthCode;
this.faceSheetForm.sendSite = res.result.sendSite;
this.faceSheetForm.sendStaff = res.result.sendStaff;
this.faceSheetForm.payType = res.result.payType;
this.faceSheetForm.expType = res.result.expType;
}
});
this.openModal = true;
},
frontDownload(val) {
const a = document.createElement("a");
if (val === "use") {
a.href = "static/instructions.xlsx";
a.download = "使用说明.xlsx";
} else if (val === "type") {
a.href = "static/logisticsType.xlsx";
a.download = "快递类型.xlsx";
}
a.style.display = "none";
document.body.appendChild(a);
a.click();
a.remove();
},
submit() {
if (!this.row.selected) {
API_Shop.logisticsChecked(this.row.logisticsId, this.faceSheetForm).then((res) => {
this.openModal = false;
if (res.success) {
this.$Message.success("物流公司开启成功");
this.init();
}
});
} else {
API_Shop.editChecked(this.logisticsId, this.faceSheetForm).then((res) => {
if (res.success) {
this.$Message.success("修改成功");
this.openModal = false;
this.init();
}
});
}
},
close(v) {
this.$Modal.confirm({
title: "确认关闭",
content: "您确认关闭此物流公司?",
loading: true,
onOk: () => {
API_Shop.logisticsUnChecked(v.logisticsId).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("物流公司关闭成功");
this.init();
}
});
},
});
},
},
mounted() {
this.init();
},
};
});
}
onMounted(() => {
init();
});
</script>
<style lang="scss" scoped>

View File

@@ -62,7 +62,7 @@
</table>
</el-tab-pane>
<el-tab-pane v-if="csTab" :label="title" :name="operation">
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="模板名称" prop="name">
<el-input v-model="form.name" maxlength="10" clearable style="width: 20%" />
</el-form-item>
@@ -175,264 +175,86 @@
</div>
</template>
<script>
<script setup>
import { ref, computed, onMounted } from "vue";
import * as API_Shop from "@/api/shops";
import multipleRegion from "@/views/lili-components/multiple-region";
import { useAppStore } from "@/stores/app";
import { Message, Modal } from "@/utils/message";
export default {
defineOptions({
name: "shipTemplate",
components: {
multipleRegion,
},
data() {
return {
gotop: false,
index:'0',
selectedIndex: 0, //选中的地址模板下标
item: "", //运费模板子模板
shipInfo: [], // 运费模板数据
title: "添加运费模板", // 模态框标题
operation: "INFO", // 操作状态
currentTab: "INFO", // 当前模板tab
// submitLoading:false,
saveError: false, // 是否显示错误提示
csTab: false, // 添加运费模板显示
form: {
// 添加或编辑表单对象初始化数据
name: "",
pricingMethod: "WEIGHT",
},
formValidate: {
name: [
{
required: true,
message: "请输入模板名称",
trigger: "blur",
},
],
pricingMethod: [
// 计费方式
{
required: true,
message: "请选择计费方式",
trigger: "blur",
},
],
},
};
},
computed: {
regions() {
return this.$store.state.regions;
},
},
methods: {
// 初始化数据
init() {
this.currentTab = "INFO";
this.csTab = false;
this.operation = "INFO";
this.getData();
},
//切换tabPane
handleClickType(tab) {
const tabName = tab.paneName ?? tab.props?.name;
if (tabName === "INFO") {
this.getData();
this.csTab = false;
}
},
//添加运费模板
add() {
this.$refs.region.clear();
this.title = "添加运费模板";
this.csTab = true;
this.operation = "ADD";
this.currentTab = "ADD";
this.saveError = false;
this.form = {
pricingMethod: "WEIGHT",
name: "",
freightTemplateChildList: [
{
area: "",
areaId: "",
firstCompany: 0,
firstPrice: 0,
continuedCompany: 0,
continuedPrice: 0,
selectedAll: false,
},
],
};
},
handleScroll(){
let scrolltop = document.documentElement.scrollTop || document.body.scrollTop;
scrolltop > 30 ? (this.gotop = true) : (this.gotop = false);
},
//修改运费模板
edit(item) {
this.title = "修改运费模板";
this.csTab = true;
this.operation = "EDIT";
this.currentTab = "EDIT";
this.saveError = false;
//给form赋值
this.form = item;
});
let top = document.documentElement.scrollTop || document.body.scrollTop;
// 实现滚动效果
const timeTop = setInterval(() => {
document.body.scrollTop = document.documentElement.scrollTop = top -= 50;
if (top <= 0) {
clearInterval(timeTop);
}
}, 0);
},
//选择地区
editRegion(item, index) {
this.selectedIndex = index;
this.item = item;
const appStore = useAppStore();
this.regions.forEach((addr) => {
this.form.freightTemplateChildList.forEach((child) => {
child.area.split(",").forEach((area) => {
if (addr.name == area) {
addr.selectedAll = true;
child.selectedAll = true;
}
});
});
});
this.$store.state.shipTemplate = this.form.freightTemplateChildList;
this.$refs.region.open(item, index);
const gotop = ref(false);
const index = ref("0");
const selectedIndex = ref(0); //选中的地址模板下标
const curItem = ref(""); //运费模板子模板
const shipInfo = ref([]); // 运费模板数据
const title = ref("添加运费模板"); // 模态框标题
const operation = ref("INFO"); // 操作状态
const currentTab = ref("INFO"); // 当前模板tab
// submitLoading:false,
const saveError = ref(false); // 是否显示错误提示
const csTab = ref(false); // 添加运费模板显示
const form = ref({
// 添加或编辑表单对象初始化数据
name: "",
pricingMethod: "WEIGHT",
});
const formValidate = {
name: [
{
required: true,
message: "请输入模板名称",
trigger: "blur",
},
//刷细数据
refresh() {
this.csTab = false;
this.operation = "INFO";
this.currentTab = "INFO";
this.getData();
this.$Message.success("刷新成功");
],
pricingMethod: [
// 计费方式
{
required: true,
message: "请选择计费方式",
trigger: "blur",
},
//运费模板数据
getData() {
API_Shop.getShipTemplate().then((res) => {
this.shipInfo = Array.isArray(res.result) ? res.result : [];
});
},
/**
* 选择地址回调
*/
handleSelect(v) {
let area = "";
let areaId = "";
if (v != "") {
v.forEach((child) => {
if (child.selectedList != "") {
// 只显示省份
],
};
if (child.selectedAll) {
area += child.name + ",";
this.form.freightTemplateChildList[
this.selectedIndex
].selectedAll = true;
}
const formRef = ref(null);
const region = ref(null);
child.selectedList.forEach((son) => {
if (child.selectedAll) {
areaId += son.id + ",";
return;
} else {
// 显示城市
area += son.name + ",";
areaId += son.id + ",";
}
});
}
});
}
this.item.area = area;
this.item.areaId = areaId;
},
//添加或者修改运费模板
handleSubmit() {
const headers = {
"Content-Type": "application/json;charset=utf-8",
};
const regions = computed(() => appStore.regions);
this.$refs.form.validate((valid) => {
// const regNumber = /^\+?[1-9][0-9]*$/;
// const regMoney =
// /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/;
if (valid) {
if (this.form.pricingMethod != "FREE") {
//校验运费模板详细信息
for (
let i = 0;
i < this.form.freightTemplateChildList.length;
i++
) {
if (
this.form.freightTemplateChildList[i].area == "" ||
this.form.freightTemplateChildList[i].firstCompany == "" ||
// this.form.freightTemplateChildList[i].firstPrice == "" ||
this.form.freightTemplateChildList[i].continuedCompany == ""
// this.form.freightTemplateChildList[i].continuedPrice == ""
) {
this.saveError = true;
return;
}
// if (
// regNumber.test(
// this.form.freightTemplateChildList[i].firstCompany
// ) == false ||
// regNumber.test(
// this.form.freightTemplateChildList[i].continuedCompany
// ) == false ||
// regMoney.test(
// this.form.freightTemplateChildList[i].firstPrice
// ) == false ||
// regMoney.test(
// this.form.freightTemplateChildList[i].continuedPrice
// ) == false
// ) {
// this.saveError = true;
// return;
// }
}
}
if (this.operation == "ADD") {
API_Shop.addShipTemplate(this.form, headers).then((res) => {
if (res.success) {
this.$Message.success("新增成功");
this.operation = "INFO";
this.currentTab = "INFO";
this.csTab = false;
this.getData();
}
});
} else {
API_Shop.editShipTemplate(this.form.id, this.form, headers).then(
(res) => {
if (res.success) {
this.$Message.success("新增成功");
this.operation = "INFO";
this.currentTab = "INFO";
this.csTab = false;
this.getData();
}
}
);
}
}
});
},
//添加子模板
addShipTemplateChildren() {
const params = {
// 初始化数据
function init() {
currentTab.value = "INFO";
csTab.value = false;
operation.value = "INFO";
getData();
}
//切换tabPane
function handleClickType(tab) {
const tabName = tab.paneName ?? tab.props?.name;
if (tabName === "INFO") {
getData();
csTab.value = false;
}
}
//添加运费模板
function add() {
region.value.clear();
title.value = "添加运费模板";
csTab.value = true;
operation.value = "ADD";
currentTab.value = "ADD";
saveError.value = false;
form.value = {
pricingMethod: "WEIGHT",
name: "",
freightTemplateChildList: [
{
area: "",
areaId: "",
firstCompany: 0,
@@ -440,41 +262,218 @@ export default {
continuedCompany: 0,
continuedPrice: 0,
selectedAll: false,
};
this.form.freightTemplateChildList.push(params);
},
//删除一个子模板
removeTemplateChildren(index) {
if (Object.keys(this.form.freightTemplateChildList).length == 1) {
this.$Message.error("必须保留一个子模板");
return;
},
],
};
}
function handleScroll() {
let scrolltop = document.documentElement.scrollTop || document.body.scrollTop;
scrolltop > 30 ? (gotop.value = true) : (gotop.value = false);
}
//修改运费模板
function edit(item) {
title.value = "修改运费模板";
csTab.value = true;
operation.value = "EDIT";
currentTab.value = "EDIT";
saveError.value = false;
//给form赋值
form.value = item;
let top = document.documentElement.scrollTop || document.body.scrollTop;
// 实现滚动效果
const timeTop = setInterval(() => {
document.body.scrollTop = document.documentElement.scrollTop = top -= 50;
if (top <= 0) {
clearInterval(timeTop);
}
}, 0);
}
//选择地区
function editRegion(item, index) {
selectedIndex.value = index;
curItem.value = item;
regions.value.forEach((addr) => {
form.value.freightTemplateChildList.forEach((child) => {
child.area.split(",").forEach((area) => {
if (addr.name == area) {
addr.selectedAll = true;
child.selectedAll = true;
}
});
});
});
appStore.shipTemplates = form.value.freightTemplateChildList;
region.value.open(item, index);
}
//刷细数据
function refresh() {
csTab.value = false;
operation.value = "INFO";
currentTab.value = "INFO";
getData();
Message.success("刷新成功");
}
//运费模板数据
function getData() {
API_Shop.getShipTemplate().then((res) => {
shipInfo.value = Array.isArray(res.result) ? res.result : [];
});
}
/**
* 选择地址回调
*/
function handleSelect(v) {
let area = "";
let areaId = "";
if (v != "") {
v.forEach((child) => {
if (child.selectedList != "") {
// 只显示省份
if (child.selectedAll) {
area += child.name + ",";
form.value.freightTemplateChildList[
selectedIndex.value
].selectedAll = true;
}
child.selectedList.forEach((son) => {
if (child.selectedAll) {
areaId += son.id + ",";
return;
} else {
// 显示城市
area += son.name + ",";
areaId += son.id + ",";
}
});
}
this.form.freightTemplateChildList.splice(index, 1);
},
//删除运费模板
remove(id) {
this.$Modal.confirm({
title: "确认删除",
// 记得确认修改此处
content: "您确认要删除此运费模板 ?",
loading: true,
onOk: () => {
API_Shop.deleteShipTemplate(id).then((res) => {
});
}
curItem.value.area = area;
curItem.value.areaId = areaId;
}
//添加或者修改运费模板
function handleSubmit() {
const headers = {
"Content-Type": "application/json;charset=utf-8",
};
formRef.value.validate((valid) => {
// const regNumber = /^\+?[1-9][0-9]*$/;
// const regMoney =
// /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/;
if (valid) {
if (form.value.pricingMethod != "FREE") {
//校验运费模板详细信息
for (
let i = 0;
i < form.value.freightTemplateChildList.length;
i++
) {
if (
form.value.freightTemplateChildList[i].area == "" ||
form.value.freightTemplateChildList[i].firstCompany == "" ||
// form.value.freightTemplateChildList[i].firstPrice == "" ||
form.value.freightTemplateChildList[i].continuedCompany == ""
// form.value.freightTemplateChildList[i].continuedPrice == ""
) {
saveError.value = true;
return;
}
// if (
// regNumber.test(
// form.value.freightTemplateChildList[i].firstCompany
// ) == false ||
// regNumber.test(
// form.value.freightTemplateChildList[i].continuedCompany
// ) == false ||
// regMoney.test(
// form.value.freightTemplateChildList[i].firstPrice
// ) == false ||
// regMoney.test(
// form.value.freightTemplateChildList[i].continuedPrice
// ) == false
// ) {
// saveError.value = true;
// return;
// }
}
}
if (operation.value == "ADD") {
API_Shop.addShipTemplate(form.value, headers).then((res) => {
if (res.success) {
Message.success("新增成功");
operation.value = "INFO";
currentTab.value = "INFO";
csTab.value = false;
getData();
}
});
} else {
API_Shop.editShipTemplate(form.value.id, form.value, headers).then(
(res) => {
if (res.success) {
this.$Message.success("删除成功");
Message.success("新增成功");
operation.value = "INFO";
currentTab.value = "INFO";
csTab.value = false;
getData();
}
this.$Modal.remove();
this.getData();
});
},
}
);
}
}
});
}
//添加子模板
function addShipTemplateChildren() {
const params = {
area: "",
areaId: "",
firstCompany: 0,
firstPrice: 0,
continuedCompany: 0,
continuedPrice: 0,
selectedAll: false,
};
form.value.freightTemplateChildList.push(params);
}
//删除一个子模板
function removeTemplateChildren(index) {
if (Object.keys(form.value.freightTemplateChildList).length == 1) {
Message.error("必须保留一个子模板");
return;
}
form.value.freightTemplateChildList.splice(index, 1);
}
//删除运费模板
function remove(id) {
Modal.confirm({
title: "确认删除",
// 记得确认修改此处
content: "您确认要删除此运费模板 ?",
loading: true,
onOk: () => {
API_Shop.deleteShipTemplate(id).then((res) => {
if (res.success) {
Message.success("删除成功");
}
Modal.remove();
getData();
});
},
},
mounted() {
this.init();
window.addEventListener("scroll", this.handleScroll, true);
},
};
});
}
onMounted(() => {
init();
window.addEventListener("scroll", handleScroll, true);
});
</script>
<style lang="scss" scoped>
.ncsc-default-table thead th {

View File

@@ -40,7 +40,7 @@
width="500px"
:close-on-click-modal="false"
>
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="名称" prop="addressName">
<el-input v-model="form.addressName" clearable style="width: 90%" />
</el-form-item>
@@ -61,156 +61,154 @@
</div>
</template>
<script>
<script setup>
import { nextTick, onMounted, reactive, ref } from "vue";
import * as API_Shop from "@/api/shops";
import { validateMobile } from "@/libs/validate";
import { Message, Modal } from "@/utils/message";
import multipleMap from "@/views/my-components/map/multiple-map";
export default {
name: "shopAddress",
components: { multipleMap },
data() {
return {
loading: true,
modalType: 0,
modalVisible: false,
modalTitle: "",
searchForm: {
pageNumber: 1,
pageSize: 10,
},
form: {
addressName: "",
center: "",
address: "",
mobile: "",
},
formValidate: {
addressName: [{ required: true, message: "请输入地址名称", trigger: "blur" }],
longitude: [{ required: true, message: "请输入地址经度", trigger: "blur" }],
latitude: [{ required: true, message: "请输入地址纬度", trigger: "blur" }],
mobile: [
{ required: true, message: "请输入联系电话号", trigger: "blur" },
{ validator: validateMobile, trigger: "blur" },
],
address: [{ required: true, message: " ", trigger: "blur" }],
},
submitLoading: false,
data: [],
total: 0,
};
},
methods: {
init() {
this.getDataList();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
getAddress(val) {
if (val.type === "select") {
const paths = val.data.map((item) => item.name).join(",");
this.form.address = paths;
this.form.center = val.data[val.data.length - 1].center;
} else {
this.form.address = val.data.addr;
this.form.address = val.data.address;
this.form.center = val.data.position.lng + "," + val.data.position.lat;
}
},
getDataList() {
this.loading = true;
API_Shop.getShopAddress(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
resetForm() {
this.form = {
addressName: "",
center: "",
address: "",
mobile: "",
};
},
add() {
this.modalType = 0;
this.modalTitle = "添加自提地址";
this.resetForm();
this.modalVisible = true;
this.$nextTick(() => {
this.$refs.form?.resetFields();
});
},
edit(v) {
this.modalType = 1;
this.modalVisible = true;
this.modalTitle = "修改自提地址";
this.form.id = v.id;
this.form.address = v.address;
this.form.addressName = v.addressName;
this.form.mobile = v.mobile;
this.form.center = v.center;
this.form.longitude = v.center.split(",")[0];
this.form.latitude = v.center.split(",")[1];
},
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.submitLoading = true;
if (this.modalType == 0) {
const params = { ...this.form };
delete params.id;
API_Shop.addShopAddress(params).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("添加成功");
this.getDataList();
this.modalVisible = false;
}
});
} else {
API_Shop.editShopAddress(this.form.id, this.form).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getDataList();
this.modalVisible = false;
}
});
}
}
});
},
deleteSubmit(v) {
this.$Modal.confirm({
title: "确认删除",
content: "确认删除自提地址么?",
loading: true,
onOk: () => {
API_Shop.deleteShopAddress(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("此自自提地址已删除");
this.init();
}
});
},
});
},
},
mounted() {
this.init();
},
defineOptions({ name: "shopAddress" });
const formRef = ref(null);
const loading = ref(true);
const modalType = ref(0);
const modalVisible = ref(false);
const modalTitle = ref("");
const searchForm = reactive({
pageNumber: 1,
pageSize: 10,
});
const form = ref({
addressName: "",
center: "",
address: "",
mobile: "",
});
const formValidate = {
addressName: [{ required: true, message: "请输入地址名称", trigger: "blur" }],
longitude: [{ required: true, message: "请输入地址经度", trigger: "blur" }],
latitude: [{ required: true, message: "请输入地址纬度", trigger: "blur" }],
mobile: [
{ required: true, message: "请输入联系电话号", trigger: "blur" },
{ validator: validateMobile, trigger: "blur" },
],
address: [{ required: true, message: " ", trigger: "blur" }],
};
const submitLoading = ref(false);
const data = ref([]);
const total = ref(0);
function init() {
getDataList();
}
function changePage(v) {
searchForm.pageNumber = v;
getDataList();
}
function changePageSize(v) {
searchForm.pageSize = v;
getDataList();
}
function getAddress(val) {
if (val.type === "select") {
const paths = val.data.map((item) => item.name).join(",");
form.value.address = paths;
form.value.center = val.data[val.data.length - 1].center;
} else {
form.value.address = val.data.addr;
form.value.address = val.data.address;
form.value.center = val.data.position.lng + "," + val.data.position.lat;
}
}
function getDataList() {
loading.value = true;
API_Shop.getShopAddress(searchForm).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function resetForm() {
form.value = {
addressName: "",
center: "",
address: "",
mobile: "",
};
}
function add() {
modalType.value = 0;
modalTitle.value = "添加自提地址";
resetForm();
modalVisible.value = true;
nextTick(() => {
formRef.value?.resetFields();
});
}
function edit(v) {
modalType.value = 1;
modalVisible.value = true;
modalTitle.value = "修改自提地址";
form.value.id = v.id;
form.value.address = v.address;
form.value.addressName = v.addressName;
form.value.mobile = v.mobile;
form.value.center = v.center;
form.value.longitude = v.center.split(",")[0];
form.value.latitude = v.center.split(",")[1];
}
function handleSubmit() {
formRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true;
if (modalType.value == 0) {
const params = { ...form.value };
delete params.id;
API_Shop.addShopAddress(params).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("添加成功");
getDataList();
modalVisible.value = false;
}
});
} else {
API_Shop.editShopAddress(form.value.id, form.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("修改成功");
getDataList();
modalVisible.value = false;
}
});
}
}
});
}
function deleteSubmit(v) {
Modal.confirm({
title: "确认删除",
content: "确认删除自提地址么?",
loading: true,
onOk: () => {
API_Shop.deleteShopAddress(v.id).then((res) => {
Modal.remove();
if (res.success) {
Message.success("此自自提地址已删除");
init();
}
});
},
});
}
onMounted(() => {
init();
});
</script>
<style scoped>
.link-text {

View File

@@ -3,7 +3,7 @@
<el-card style="margin-left: 10px">
<el-tabs v-model="type" @click="handleClickType">
<el-tab-pane label="基本信息" name="INFO">
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="店铺名称">
<el-input v-model="storeName" disabled clearable style="width: 20%" />
</el-form-item>
@@ -35,7 +35,7 @@
</el-form>
</el-tab-pane>
<el-tab-pane label="发货地址">
<el-form ref="addressGoods" :model="addressGoods" label-width="120px" :rules="addressGoodsValidate" class="shop-setting-form">
<el-form ref="addressGoodsRef" :model="addressGoods" label-width="120px" :rules="addressGoodsValidate" class="shop-setting-form">
<el-form-item label="发货人姓名" prop="salesConsignorName">
<el-input v-model="addressGoods.salesConsignorName" maxlength="11" clearable style="width: 20%">
</el-input>
@@ -65,7 +65,7 @@
</el-form>
</el-tab-pane>
<el-tab-pane label="退货地址" name="REFUND_GOODS_ADDRESS">
<el-form ref="addressForm" :model="addressForm" label-width="100px" :rules="afterFormValidate">
<el-form ref="addressFormRef" :model="addressForm" label-width="100px" :rules="afterFormValidate">
<el-form-item label="收货人" prop="salesConsigneeName">
<el-input v-model="addressForm.salesConsigneeName" maxlength="11" clearable style="width: 20%" />
</el-form-item>
@@ -116,325 +116,327 @@
</el-tabs>
</el-card>
<multipleMap ref="map" @callback="callbackAddress" />
<multipleMap ref="mapRef" @callback="callbackAddress" />
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import * as API_Shop from "@/api/shops";
import { validateMobile } from "@/libs/validate";
import uploadPicThumb from "@/views/my-components/lili/upload-pic-thumb";
import multipleMap from "@/views/my-components/map/multiple-map";
import * as RegExp from "@/libs/RegExp.js";
import Cookies from "js-cookie";
export default {
name: "shopSetting",
components: {
uploadPicThumb,
import { Message } from "@/utils/message";
multipleMap
},
data() {
return {
currentKey: "", //存储当前点击地址的key
showMap: false, // 是否展示地图
type: "INFO",
defineOptions({ name: "shopSetting" });
storeName: "", //店铺名称
const currentKey = ref(""); //存储当前点击地址的key
const showMap = ref(false); // 是否展示地图
const type = ref("INFO");
regionId: [], // 地区id
addressForm: {
// 退货地址
salesConsigneeName: "", // 收货人姓名
salesConsigneeMobile: "", // 收货人电话
salesConsigneeAddressId: "", // 售后地址id,逗号分割
salesConsigneeAddressPath: "", // 售后地址,逗号分割
salesConsigneeDetail: "", // 详细地址
},
//im form
udeskForm: {
merchantEuid: "",
},
udeskFormValidate: {
merchantEuid: [
{ required: true, message: "请输入店铺坐席ID", trigger: "blur" },
],
},
afterFormValidate: {
salesConsigneeMobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" },
{
pattern: RegExp.mobile,
trigger: "blur",
message: "请输入正确的手机号",
},
],
salesConsigneeName: [
{ required: true, message: "请输入收货人", trigger: "blur" },
],
salesConsigneeDetail: [
{ required: true, message: "请输入详细地址", trigger: "blur" },
],
},
form: {
// 添加或编辑表单对象初始化数据
storeAddressPath: "", // 店铺地址中文
storeCenter: "", // 经度 + 纬度
longitude: "", //经度
latitude: "", //纬度
storeAddressDetail: "", //详细地址
storeAddressIdPath: "", //地址
storeDesc: "", // 店铺描述
pageShow: false,
selfPickFlag: false,
},
const storeName = ref(""); //店铺名称
// 表单验证规则
formValidate: {
addressName: [
{
required: true,
message: "请输入地址名称",
trigger: "blur",
},
],
longitude: [
{
required: true,
message: "请输入地址经度",
trigger: "blur",
},
],
latitude: [
{
required: true,
message: "请输入地址纬度",
trigger: "blur",
},
],
mobile: [
{
required: true,
message: "请输入地址纬度",
trigger: "blur",
},
{
validator: validateMobile,
trigger: "blur",
},
],
storeAddressDetail: [
{
required: true,
message: "请输入详细地址",
trigger: "blur",
},
],
},
submitLoading: false, // 添加或编辑提交状态
//发货地址
addressGoods: {
salesConsignorName: " ",
salesConsignorMobile: " ",
salesConsignorAddressId: " ",
salesConsignorAddressPath: " ",
salesConsignorDetail: " ",
},
addressGoodsValidate: {
salesConsignorName: [
{ required: true, message: "请输入发货人姓名", trigger: "blur" },
],
salesConsignorMobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" },
{
pattern: RegExp.mobile,
trigger: "blur",
message: "请输入正确的手机号",
},
],
salesConsignorDetail: [
{ required: true, message: "请输入详细地址", trigger: "blur" },
],
},
};
},
methods: {
// 回调地址
callbackAddress(val) {
if (val.type === 'select') {
const paths = val.data.map(item => item.name).join(',')
const ids = val.data.map(item => item.id).join(',')
if (this.currentKey === 'storeAddress') {
this.form.storeAddressPath = paths
this.form.storeAddressIdPath = ids
this.form.storeCenter = val.data[val.data.length - 1].center
}
if (this.currentKey === 'addressGoods') {
this.addressGoods.salesConsignorAddressPath = paths
this.addressGoods.salesConsignorAddressId = ids
}
if (this.currentKey === 'salesConsigneeAddressPath') {
this.addressForm.salesConsigneeAddressPath = paths
this.addressForm.salesConsigneeAddressId = ids
}
}
else {
if (this.currentKey === 'storeAddressstoreAddress') {
this.form.storeAddressPath = val.data.addr;
this.form.storeAddressIdPath = val.data.addrId;
this.form.storeCenter = val.data.position.lng + "," + val.data.position.lat;
}
if (this.currentKey === 'addressGoods') {
this.addressGoods.salesConsignorAddressPath = val.data.addr;
this.addressGoods.salesConsignorAddressId = val.data.addrId;
}
if (this.currentKey === 'salesConsigneeAddressPath') {
this.addressForm.salesConsigneeAddressPath = val.data.addr;
this.addressForm.salesConsigneeAddressId = val.data.addrId;
}
}
const regionId = ref([]); // 地区id
// 历史遗留:loading、regionGoods、regionIdS 未在原 data 中声明,仅在方法内赋值,保持原行为
let loading = false;
let regionGoods = null;
let regionIdS = null;
const addressForm = ref({
// 退货地址
salesConsigneeName: "", // 收货人姓名
salesConsigneeMobile: "", // 收货人电话
salesConsigneeAddressId: "", // 售后地址id,逗号分割
salesConsigneeAddressPath: "", // 售后地址,逗号分割
salesConsigneeDetail: "", // 详细地址
});
//im form
const udeskForm = ref({
merchantEuid: "",
});
const udeskFormValidate = {
merchantEuid: [
{ required: true, message: "请输入店铺坐席ID", trigger: "blur" },
],
};
const afterFormValidate = {
salesConsigneeMobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" },
{
pattern: RegExp.mobile,
trigger: "blur",
message: "请输入正确的手机号",
},
// 修改地址
handleChangeAddress(key) {
this.currentKey = key
this.$refs.map.open();
],
salesConsigneeName: [
{ required: true, message: "请输入收货人", trigger: "blur" },
],
salesConsigneeDetail: [
{ required: true, message: "请输入详细地址", trigger: "blur" },
],
};
const form = ref({
// 添加或编辑表单对象初始化数据
storeAddressPath: "", // 店铺地址中文
storeCenter: "", // 经度 + 纬度
longitude: "", //经度
latitude: "", //纬度
storeAddressDetail: "", //详细地址
storeAddressIdPath: "", //地址
storeDesc: "", // 店铺描述
pageShow: false,
selfPickFlag: false,
});
// 表单验证规则
const formValidate = {
addressName: [
{
required: true,
message: "请输入地址名称",
trigger: "blur",
},
// 初始化数据
init() {
this.getShopInfo();
this.getDeliverAddress()
],
longitude: [
{
required: true,
message: "请输入地址经度",
trigger: "blur",
},
],
latitude: [
{
required: true,
message: "请输入地址纬度",
trigger: "blur",
},
],
mobile: [
{
required: true,
message: "请输入地址纬度",
trigger: "blur",
},
{
validator: validateMobile,
trigger: "blur",
},
],
storeAddressDetail: [
{
required: true,
message: "请输入详细地址",
trigger: "blur",
},
],
};
const submitLoading = ref(false); // 添加或编辑提交状态
//发货地址
const addressGoods = ref({
salesConsignorName: " ",
salesConsignorMobile: " ",
salesConsignorAddressId: " ",
salesConsignorAddressPath: " ",
salesConsignorDetail: " ",
});
const addressGoodsValidate = {
salesConsignorName: [
{ required: true, message: "请输入发货人姓名", trigger: "blur" },
],
salesConsignorMobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" },
{
pattern: RegExp.mobile,
trigger: "blur",
message: "请输入正确的手机号",
},
],
salesConsignorDetail: [
{ required: true, message: "请输入详细地址", trigger: "blur" },
],
};
const formRef = ref(null);
const addressGoodsRef = ref(null);
const addressFormRef = ref(null);
const udeskFormRef = ref(null);
const mapRef = ref(null);
// 回调地址
function callbackAddress(val) {
if (val.type === 'select') {
const paths = val.data.map(item => item.name).join(',')
const ids = val.data.map(item => item.id).join(',')
if (currentKey.value === 'storeAddress') {
form.value.storeAddressPath = paths
form.value.storeAddressIdPath = ids
form.value.storeCenter = val.data[val.data.length - 1].center
}
if (currentKey.value === 'addressGoods') {
addressGoods.value.salesConsignorAddressPath = paths
addressGoods.value.salesConsignorAddressId = ids
}
if (currentKey.value === 'salesConsigneeAddressPath') {
addressForm.value.salesConsigneeAddressPath = paths
addressForm.value.salesConsigneeAddressId = ids
}
}
else {
if (currentKey.value === 'storeAddressstoreAddress') {
form.value.storeAddressPath = val.data.addr;
form.value.storeAddressIdPath = val.data.addrId;
form.value.storeCenter = val.data.position.lng + "," + val.data.position.lat;
}
if (currentKey.value === 'addressGoods') {
addressGoods.value.salesConsignorAddressPath = val.data.addr;
addressGoods.value.salesConsignorAddressId = val.data.addrId;
}
if (currentKey.value === 'salesConsigneeAddressPath') {
addressForm.value.salesConsigneeAddressPath = val.data.addr;
addressForm.value.salesConsigneeAddressId = val.data.addrId;
}
}
}
// 修改地址
function handleChangeAddress(key) {
currentKey.value = key
mapRef.value.open();
}
// 初始化数据
function init() {
getShopInfo();
getDeliverAddress()
}
setAddressGoods() {
console.log(this.$refs.addressGoods)
function setAddressGoods() {
console.log(addressGoodsRef.value)
this.$refs.addressGoods.validate((valid) => {
if (valid) {
API_Shop.editDeliverAddress(this.addressGoods).then(res => {
if (res.success) {
this.$Message.success("修改成功")
}
})
}
});
},
//获取店铺信息
getShopInfo() {
this.loading = true;
API_Shop.getShopInfo().then((res) => {
this.loading = false;
addressGoodsRef.value.validate((valid) => {
if (valid) {
API_Shop.editDeliverAddress(addressGoods.value).then(res => {
if (res.success) {
this.form = res.result;
this.storeName = res.result.storeName;
this.form.storeCenter = res.result.storeCenter;
Cookies.set("userInfoSeller", JSON.stringify(res.result));
if (res.result.merchantEuid) {
//赋予坐席id
this.udeskForm.merchantEuid = res.result.merchantEuid;
}
}
});
},
pageShow(type) {
this.form.pageShow = type
},
changeSelfPickFlag(item) {
if (item) {
this.form.selfPickFlag = item
}
},
getDeliverAddress() {
API_Shop.getDeliverAddress().then(res => {
if (res.success) {
if (res.result != '' && res.result != null) {
this.addressGoods = res.result;
this.regionGoods = res.result.salesConsignorAddressPath;
this.regionIdS = res.result.salesConsignorAddressId;
}
Message.success("修改成功")
}
})
},
}
});
}
//获取店铺信息
function getShopInfo() {
loading = true;
API_Shop.getShopInfo().then((res) => {
loading = false;
if (res.success) {
form.value = res.result;
//重置
handleReset() {
this.$refs.form.resetFields();
},
//提交保存
handleSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.submitLoading = true;
API_Shop.saveShopInfo(this.form).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getShopInfo();
}
});
}
});
},
merchantSubmit() {
this.$refs.udeskForm.validate((valid) => {
if (valid) {
this.submitLoading = true;
API_Shop.updatEmerchantId(this.udeskForm).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getShopInfo();
}
});
}
});
},
storeName.value = res.result.storeName;
form.value.storeCenter = res.result.storeCenter;
Cookies.set("userInfoSeller", JSON.stringify(res.result));
if (res.result.merchantEuid) {
//赋予坐席id
udeskForm.value.merchantEuid = res.result.merchantEuid;
}
}
});
}
function pageShow(type) {
form.value.pageShow = type
}
function changeSelfPickFlag(item) {
if (item) {
form.value.selfPickFlag = item
}
}
function getDeliverAddress() {
API_Shop.getDeliverAddress().then(res => {
if (res.success) {
if (res.result != '' && res.result != null) {
addressGoods.value = res.result;
regionGoods = res.result.salesConsignorAddressPath;
regionIdS = res.result.salesConsignorAddressId;
}
}
})
}
//tab切换
handleClickType(v) {
//退款
if (v == "INFO") {
this.getShopInfo();
}
//退货
if (v == "REFUND_GOODS_ADDRESS") {
this.getRefundGoodsAddress();
}
},
//获取商家退货地址
getRefundGoodsAddress() {
API_Shop.getRefundGoodsAddress().then((res) => {
if (res.result != null) {
this.addressForm = res.result;
//重置
function handleReset() {
formRef.value.resetFields();
}
//提交保存
function handleSubmit() {
formRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true;
API_Shop.saveShopInfo(form.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("修改成功");
getShopInfo();
}
});
},
//提交保存
afterHandleSubmit() {
this.$refs.addressForm.validate((valid) => {
if (valid) {
this.submitLoading = true;
API_Shop.saveRefundGoodsAddress(this.addressForm).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("修改成功");
this.getRefundGoodsAddress();
}
});
}
});
}
function merchantSubmit() {
udeskFormRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true;
API_Shop.updatEmerchantId(udeskForm.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("修改成功");
getShopInfo();
}
});
},
},
mounted() {
this.init();
},
};
}
});
}
//tab切换
function handleClickType(v) {
//退款
if (v == "INFO") {
getShopInfo();
}
//退货
if (v == "REFUND_GOODS_ADDRESS") {
getRefundGoodsAddress();
}
}
//获取商家退货地址
function getRefundGoodsAddress() {
API_Shop.getRefundGoodsAddress().then((res) => {
if (res.result != null) {
addressForm.value = res.result;
}
});
}
//提交保存
function afterHandleSubmit() {
addressFormRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true;
API_Shop.saveRefundGoodsAddress(addressForm.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("修改成功");
getRefundGoodsAddress();
}
});
}
});
}
onMounted(() => {
init();
});
</script>
<style scoped lang="scss">
.desc {

View File

@@ -1,7 +1,7 @@
<template>
<div class="search">
<el-card>
<el-form ref="searchForm" :model="searchForm" inline label-width="70px" class="search-form">
<el-form ref="searchFormRef" :model="searchForm" inline label-width="70px" class="search-form">
<el-form-item label="店员名称">
<el-input
type="text"
@@ -37,7 +37,7 @@
</div>
<br>
<el-table
ref="table"
ref="tableRef"
v-loading="loading"
border
:data="data"
@@ -178,9 +178,10 @@
</div>
</template>
<script>
<script setup>
import { computed, nextTick, onMounted, reactive, ref } from "vue";
import {
checkClerk,
checkClerk as fetchCheckClerk,
getUserListData,
getAllRoleList,
addUser,
@@ -190,442 +191,441 @@ import {
resetPassword,
getClerk
} from "@/api/index";
import {validateMobile} from "@/libs/validate";
import { validateMobile } from "@/libs/validate";
import { Search } from "@element-plus/icons-vue";
import { Message, Modal } from "@/utils/message";
import { md5 } from "@/utils/md5.js";
import departmentChoose from "@/views/my-components/lili/department-choose";
import departmentTreeChoose from "@/views/my-components/lili/department-tree-choose";
export default {
name: "clerk-manage",
components: {
Search,
departmentChoose,
departmentTreeChoose,
},
data() {
return {
open:0,
loading: true, // 加载状态
selectCount: 0, // 已选数量
selectList: [], // 已选数据列表
searchForm: { // 请求参数
clerkName: "",
departmentId: "",
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc"
},
modalType: 0, // 新增编辑标识
userModalVisible: false, // 用户modal显隐
userEditModalVisible:false,
modalTitle: "", // modal标题
form: { // 表单
username: "",
mobile: 0,
sex: "",
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: ""
},
defineOptions({ name: "clerk-manage" });
editForm: { // 表单
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: ""
},
mobile: "",
clerkName: "",
const searchFormRef = ref(null);
const tableRef = ref(null);
const dep = ref(null);
const editFormRef = ref(null);
const editDepTree = ref(null);
const addForm = ref(null);
const addDepTree = ref(null);
newMember: false,
oldMember: false,
memberCheck: false,
roleList: [], // 角色列表
errorPass: "", // 错误提示
formValidate: { // 验证规则
username: [
{required: true, message: "用户名不能为空", trigger: "blur"}
],
password: [
{required: true, message: "密码不能为空", trigger: "blur"}
],
mobile: [
{required: true, message: "手机号不能为空", trigger: "blur"},
{validator: validateMobile, trigger: "blur"}
]
},
submitLoading: false, // 提交状态
data: [], // 用户数据
total: 0, // 总数
};
},
computed: {
addFormRules() {
const rules = {
username: this.formValidate.username,
mobile: this.formValidate.mobile,
};
if (this.newMember) {
rules.password = this.formValidate.password;
}
return rules;
},
},
methods: {
// 初始化数据
init() {
this.getUserList();
},
checkClerks() {
this.open = this.form.mobile.length;
const open = ref(0);
const loading = ref(true); // 加载状态
const selectCount = ref(0); // 已选数量
const selectList = ref([]); // 已选数据列表
const searchForm = reactive({ // 请求参数
clerkName: "",
departmentId: "",
pageNumber: 1,
pageSize: 10,
sort: "createTime",
order: "desc"
});
const modalType = ref(0); // 新增编辑标识
const userModalVisible = ref(false); // 用户modal显隐
const userEditModalVisible = ref(false);
const modalTitle = ref(""); // modal标题
const form = ref({ // 表单
username: "",
mobile: 0,
sex: "",
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: ""
});
if(this.open == 11 ){
this.checkClerk();
}
if(this.open < 11){
this.checkAgainClerk()
}
},
// 选择部门回调
handleSelectDepTree(v) {
if (v) {
this.form.departmentId = v.departmentId;
this.form.departmentTitle = v.departmentTitle;
} else {
this.form.departmentId = "";
this.form.departmentTitle = "";
}
},
// 选择部门回调
handleEditSelectDepTree(v) {
if (v) {
this.editForm.departmentId = v.departmentId;
this.editForm.departmentTitle = v.departmentTitle;
} else {
this.editForm.departmentId = "";
this.editForm.departmentTitle = "";
}
},
//重新校验会员
checkAgainClerk() {
this.memberCheck = false;
this.newMember = false;
this.oldMember = false;
this.form.username = "";
this.form.password = "";
this.form.isSuper = 0;
this.form.roles = [];
this.errorPass = "";
},
// 检测当前手机号对应会员:无 id 为新建会员,有 id 为已有会员
checkClerk() {
if (!this.form.mobile) {
return;
}
this.newMember = false;
this.oldMember = false;
this.form.username = "";
this.form.password = "";
this.errorPass = "";
checkClerk(this.form.mobile).then((res) => {
if (!res.success) {
return;
}
if (!res.result || !res.result.id) {
// 平台无此会员,需新建账号并设置密码
this.newMember = true;
this.oldMember = false;
} else {
// 已有会员,仅绑定为店员,不需要也不应展示/回填密码
this.newMember = false;
this.oldMember = true;
this.form.username = res.result.username || "";
this.form.password = "";
}
this.form.isSuper = 0;
this.memberCheck = true;
const editForm = reactive({ // 表单
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: ""
});
const mobile = ref("");
const clerkName = ref("");
const newMember = ref(false);
const oldMember = ref(false);
const memberCheck = ref(false);
const roleList = ref([]); // 角色列表
const errorPass = ref(""); // 错误提示
const formValidate = { // 验证规则
username: [
{required: true, message: "用户名不能为空", trigger: "blur"}
],
password: [
{required: true, message: "密码不能为空", trigger: "blur"}
],
mobile: [
{required: true, message: "手机号不能为空", trigger: "blur"},
{validator: validateMobile, trigger: "blur"}
]
};
const submitLoading = ref(false); // 提交状态
const data = ref([]); // 用户数据
const total = ref(0); // 总数
const addFormRules = computed(() => {
const rules = {
username: formValidate.username,
mobile: formValidate.mobile,
};
if (newMember.value) {
rules.password = formValidate.password;
}
return rules;
});
// 初始化数据
function init() {
getUserList();
}
function checkClerks() {
open.value = form.value.mobile.length;
if (open.value == 11) {
checkClerk();
}
if (open.value < 11) {
checkAgainClerk();
}
}
// 选择部门回调
function handleSelectDepTree(v) {
if (v) {
form.value.departmentId = v.departmentId;
form.value.departmentTitle = v.departmentTitle;
} else {
form.value.departmentId = "";
form.value.departmentTitle = "";
}
}
// 选择部门回调
function handleEditSelectDepTree(v) {
if (v) {
editForm.departmentId = v.departmentId;
editForm.departmentTitle = v.departmentTitle;
} else {
editForm.departmentId = "";
editForm.departmentTitle = "";
}
}
//重新校验会员
function checkAgainClerk() {
memberCheck.value = false;
newMember.value = false;
oldMember.value = false;
form.value.username = "";
form.value.password = "";
form.value.isSuper = 0;
form.value.roles = [];
errorPass.value = "";
}
// 检测当前手机号对应会员:无 id 为新建会员,有 id 为已有会员
function checkClerk() {
if (!form.value.mobile) {
return;
}
newMember.value = false;
oldMember.value = false;
form.value.username = "";
form.value.password = "";
errorPass.value = "";
fetchCheckClerk(form.value.mobile).then((res) => {
if (!res.success) {
return;
}
if (!res.result || !res.result.id) {
// 平台无此会员,需新建账号并设置密码
newMember.value = true;
oldMember.value = false;
} else {
// 已有会员,仅绑定为店员,不需要也不应展示/回填密码
newMember.value = false;
oldMember.value = true;
form.value.username = res.result.username || "";
form.value.password = "";
}
form.value.isSuper = 0;
memberCheck.value = true;
});
}
// 搜索项部门选择
function handleSelectDep(v) {
searchForm.departmentId = v;
}
// 分页 修改页码
function changePage(v) {
searchForm.pageNumber = v;
getUserList();
clearSelectAll();
}
// 分页 修改页数
function changePageSize(v) {
searchForm.pageSize = v;
searchForm.pageNumber = 1;
getUserList();
}
function getUserList() {
// 多条件搜索用户列表
loading.value = true;
getUserListData(searchForm).then(res => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
// 搜索
function handleSearch() {
searchForm.pageNumber = 1;
searchForm.pageSize = 10;
getUserList();
}
// 排序
function changeSort(e) {
searchForm.sort = e.prop;
searchForm.order =
e.order === "ascending" ? "asc" : e.order === "descending" ? "desc" : "";
getUserList();
}
// 获取角色列表
function getRoleList() {
let params = {
pageSize: 100
}
getAllRoleList(params).then(res => {
if (res.success) {
roleList.value = res.result.records;
}
});
}
// 重置密码
function resetPass() {
if (selectCount.value == 0) {
Message.warning('请选中数据后重试!');
return
}
Modal.confirm({
title: "确认重置",
content:
"您确认要重置所选的 " +
selectCount.value +
" 条用户数据密码为【123456】?",
loading: true,
onOk: () => {
let ids = "";
selectList.value.forEach(function (e) {
ids += e.id + ",";
});
},
// 搜索项部门选择
handleSelectDep(v) {
this.searchForm.departmentId = v;
},
// 分页 修改页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getUserList();
this.clearSelectAll();
},
// 分页 修改页数
changePageSize(v) {
this.searchForm.pageSize = v;
this.searchForm.pageNumber = 1;
this.getUserList();
},
getUserList() {
// 多条件搜索用户列表
this.loading = true;
getUserListData(this.searchForm).then(res => {
this.loading = false;
ids = ids.substring(0, ids.length - 1);
resetPassword(ids).then(res => {
Modal.remove();
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getUserList();
},
// 排序
changeSort(e) {
this.searchForm.sort = e.prop;
this.searchForm.order =
e.order === "ascending" ? "asc" : e.order === "descending" ? "desc" : "";
this.getUserList();
},
// 获取角色列表
getRoleList() {
let params = {
pageSize: 100
}
getAllRoleList(params).then(res => {
if (res.success) {
this.roleList = res.result.records;
}
});
},
// 重置密码
resetPass() {
if (this.selectCount == 0) {
this.$Message.warning('请选中数据后重试!');
return
}
this.$Modal.confirm({
title: "确认重置",
content:
"您确认要重置所选的 " +
this.selectCount +
" 条用户数据密码为【123456】?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
resetPassword(ids).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.clearSelectAll();
this.getUserList();
}
});
}
});
},
updateSubmit(){
this.submitLoading = true;
editOtherUser(this.editForm.id,this.editForm).then(res => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getUserList();
this.userEditModalVisible = false;
}
});
},
// 确认提交
submitUser() {
this.$refs.addForm?.validate(valid => {
if (valid) {
const params = JSON.parse(JSON.stringify(this.form));
delete params.id;
delete params.status;
if (this.newMember) {
if (params.password == "" || params.password == undefined) {
this.errorPass = "密码不能为空";
return;
}
if (params.password.length < 6) {
this.errorPass = "密码长度不得少于6位";
return;
}
params.password = this.md5(params.password);
} else if (this.oldMember) {
// 后端 ClerkAddDTO 对 username/password 有 @NotEmpty 校验;
// 已有会员走 findByMobile 分支,不会使用该 password,仅用于通过参数校验
params.username = this.form.username;
params.password = params.password || "000000";
}
this.submitLoading = true;
addUser(params).then(res => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getUserList();
this.userModalVisible = false;
}
});
}
});
},
// 添加用户
add() {
this.modalType = 0;
this.modalTitle = "添加店员";
this.form = {
username: "",
mobile: "",
password: "",
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: "",
};
this.oldMember = false;
this.newMember = false;
this.memberCheck = false;
this.userModalVisible = true;
this.$nextTick(() => {
this.$refs.addForm?.resetFields();
this.$refs.addDepTree?.clearSelect?.();
});
},
// 编辑用户
edit(v) {
getClerk(v.id).then(res => {
if (!res.success || !res.result) {
return;
}
this.mobile = res.result.mobile;
this.clerkName = res.result.clerkName;
this.editForm.isSuper = res.result.isSuper ? 1 : 0;
this.editForm.id = res.result.id;
this.editForm.departmentId = res.result.departmentId;
const selectRolesId = [];
if (res.result.roles) {
res.result.roles.forEach(function (e) {
selectRolesId.push(e.id);
});
}
this.editForm.roles = selectRolesId;
this.modalTitle = "修改店员";
this.userEditModalVisible = true;
this.$nextTick(() => {
this.$refs.editDepTree?.setData(
res.result.departmentId,
res.result.departmentTitle
);
});
});
},
// 启用
enable(v) {
let params = {
status: true
}
this.$Modal.confirm({
title: "确认启用",
content: "您确认要启用用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
enableClerk(v.id, params).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getUserList();
}
});
}
});
},
// 禁用
disable(v) {
let params = {
status: false
}
this.$Modal.confirm({
title: "确认禁用",
content: "您确认要禁用用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
enableClerk(v.id, params).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getUserList();
}
});
}
});
},
// 删除用户
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
deleteClerk(v.id).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.getUserList();
}
});
}
});
},
// 选中状态
showSelect(e) {
this.selectList = e;
this.selectCount = e.length;
},
// 清除选中状态
clearSelectAll() {
this.$refs.table?.clearSelection();
},
// 批量删除
delAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectCount + " 条店员?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteClerk(ids).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.clearSelectAll();
this.getUserList();
}
});
Message.success("操作成功");
clearSelectAll();
getUserList();
}
});
}
},
mounted() {
this.init();
this.getRoleList();
});
}
function updateSubmit() {
submitLoading.value = true;
editOtherUser(editForm.id, editForm).then(res => {
submitLoading.value = false;
if (res.success) {
Message.success("操作成功");
getUserList();
userEditModalVisible.value = false;
}
});
}
// 确认提交
function submitUser() {
addForm.value?.validate(valid => {
if (valid) {
const params = JSON.parse(JSON.stringify(form.value));
delete params.id;
delete params.status;
if (newMember.value) {
if (params.password == "" || params.password == undefined) {
errorPass.value = "密码不能为空";
return;
}
if (params.password.length < 6) {
errorPass.value = "密码长度不得少于6位";
return;
}
params.password = md5(params.password);
} else if (oldMember.value) {
// 后端 ClerkAddDTO 对 username/password 有 @NotEmpty 校验;
// 已有会员走 findByMobile 分支,不会使用该 password,仅用于通过参数校验
params.username = form.value.username;
params.password = params.password || "000000";
}
submitLoading.value = true;
addUser(params).then(res => {
submitLoading.value = false;
if (res.success) {
Message.success("操作成功");
getUserList();
userModalVisible.value = false;
}
});
}
});
}
// 添加用户
function add() {
modalType.value = 0;
modalTitle.value = "添加店员";
form.value = {
username: "",
mobile: "",
password: "",
isSuper: 0,
roles: [],
departmentId: "",
departmentTitle: "",
};
oldMember.value = false;
newMember.value = false;
memberCheck.value = false;
userModalVisible.value = true;
nextTick(() => {
addForm.value?.resetFields();
addDepTree.value?.clearSelect?.();
});
}
// 编辑用户
function edit(v) {
getClerk(v.id).then(res => {
if (!res.success || !res.result) {
return;
}
mobile.value = res.result.mobile;
clerkName.value = res.result.clerkName;
editForm.isSuper = res.result.isSuper ? 1 : 0;
editForm.id = res.result.id;
editForm.departmentId = res.result.departmentId;
const selectRolesId = [];
if (res.result.roles) {
res.result.roles.forEach(function (e) {
selectRolesId.push(e.id);
});
}
editForm.roles = selectRolesId;
modalTitle.value = "修改店员";
userEditModalVisible.value = true;
nextTick(() => {
editDepTree.value?.setData(
res.result.departmentId,
res.result.departmentTitle
);
});
});
}
// 启用
function enable(v) {
let params = {
status: true
}
};
Modal.confirm({
title: "确认启用",
content: "您确认要启用用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
enableClerk(v.id, params).then(res => {
Modal.remove();
if (res.success) {
Message.success("操作成功");
getUserList();
}
});
}
});
}
// 禁用
function disable(v) {
let params = {
status: false
}
Modal.confirm({
title: "确认禁用",
content: "您确认要禁用用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
enableClerk(v.id, params).then(res => {
Modal.remove();
if (res.success) {
Message.success("操作成功");
getUserList();
}
});
}
});
}
// 删除用户
function remove(v) {
Modal.confirm({
title: "确认删除",
content: "您确认要删除用户 " + v.clerkName + " ?",
loading: true,
onOk: () => {
deleteClerk(v.id).then(res => {
Modal.remove();
if (res.success) {
Message.success("删除成功");
getUserList();
}
});
}
});
}
// 选中状态
function showSelect(e) {
selectList.value = e;
selectCount.value = e.length;
}
// 清除选中状态
function clearSelectAll() {
tableRef.value?.clearSelection();
}
// 批量删除
function delAll() {
if (selectCount.value <= 0) {
Message.warning("您还未选择要删除的数据");
return;
}
Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + selectCount.value + " 条店员?",
loading: true,
onOk: () => {
let ids = "";
selectList.value.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteClerk(ids).then(res => {
Modal.remove();
if (res.success) {
Message.success("删除成功");
clearSelectAll();
getUserList();
}
});
}
});
}
onMounted(() => {
init();
getRoleList();
});
</script>
<style scoped lang="scss">

View File

@@ -37,7 +37,7 @@
</div>
</el-col>
<el-col :md="15" :lg="13" :xl="9" style="margin-left: 10px">
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="部门名称" prop="title">
<el-input v-model="form.title" />
</el-form-item>
@@ -84,7 +84,7 @@
width="500px"
:close-on-click-modal="false"
>
<el-form ref="formAdd" :model="formAdd" label-width="85px" :rules="formValidate">
<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>
@@ -105,7 +105,8 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import {
initDepartment,
addDepartment,
@@ -115,266 +116,266 @@ import {
getRoleList,
updateDepartmentRole,
} from "@/api/index";
import { Message, Modal } from "@/utils/message";
export default {
name: "store-department-manage",
data() {
return {
loading: true,
maxHeight: "500px",
strict: true,
userLoading: false,
loadingEdit: false,
modalVisible: false,
selectList: [],
selectCount: 0,
showParent: false,
modalTitle: "",
editTitle: "",
selectedRole: [],
searchKey: "",
currentNodeKey: null,
treeProps: {
label: "title",
children: "children",
isLeaf: "isLeaf",
},
form: {
id: "",
title: "",
parentId: "",
parentTitle: "",
sortOrder: 0,
status: 0,
},
formAdd: {},
formValidate: {
title: [{ required: true, message: "名称不能为空", trigger: "blur" }],
sortOrder: [
{
required: true,
type: "number",
message: "排序值不能为空",
trigger: "blur",
},
],
},
submitLoading: false,
data: [],
dataEdit: [],
users: [],
};
},
methods: {
init() {
this.getParentList();
},
getParentList() {
this.loading = true;
initDepartment().then((res) => {
this.loading = false;
if (res.success) {
const list = Array.isArray(res.result) ? res.result : [];
this.data = this.bubbleSort(this.normalizeDepartmentTree(list));
}
});
},
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 {
delete node.children;
}
return node;
});
},
onNodeClick(data) {
if (!data) {
this.cancelSelect();
return;
}
const row = JSON.parse(JSON.stringify(data));
for (const attr in row) {
if (row[attr] == null) {
row[attr] = "";
}
}
this.editTitle = row.title;
this.currentNodeKey = row.id;
this.userLoading = true;
defineOptions({ name: "store-department-manage" });
getUserByDepartmentId(row.id).then((res) => {
const way = [];
res.result &&
res.result.forEach((item) => {
way.push(item.roleId);
});
this.selectedRole = way;
});
const treeRef = ref(null);
const formRef = ref(null);
const formAddRef = ref(null);
getRoleList({
pageNumber: 1,
pageSize: 10000,
}).then((res) => {
this.userLoading = false;
if (res.success) {
this.users = res.result.records;
this.form = row;
}
});
},
onCheckChange(_data, { checkedNodes }) {
this.selectList = checkedNodes;
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++) {
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;
},
cancelSelect() {
this.$refs.treeRef?.setCurrentKey(null);
this.currentNodeKey = null;
this.$refs.form.resetFields();
delete this.form.id;
this.editTitle = "";
this.selectedRole = [];
},
selectTreeEdit(v) {
if (v.length > 0) {
for (const attr in v[0]) {
if (v[0][attr] == null) {
v[0][attr] = "";
}
}
const data = JSON.parse(JSON.stringify(v[0]));
this.form.parentId = data.id;
this.form.parentTitle = data.title;
}
},
cancelAdd() {
this.modalVisible = false;
},
handleReset() {
this.$refs.form.resetFields();
this.form.status = 0;
},
submitEdit() {
this.$refs.form.validate((valid) => {
if (valid) {
if (!this.form.id) {
this.$Message.warning("请先点击选择要修改的部门");
return;
}
const roleWay = [];
this.selectedRole.forEach((item) => {
roleWay.push({
departmentId: this.form.id,
roleId: item,
});
});
Promise.all([
editDepartment(this.form.id, this.form),
updateDepartmentRole(this.form.id, roleWay),
]).then((res) => {
this.submitLoading = false;
if (res[0].success) {
this.$Message.success("编辑成功");
this.init();
this.modalVisible = false;
}
});
}
});
},
submitAdd() {
this.$refs.formAdd.validate((valid) => {
if (valid) {
this.submitLoading = true;
addDepartment(this.formAdd).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("添加成功");
this.init();
this.modalVisible = false;
}
});
}
});
},
add() {
if (this.form.id == "" || this.form.id == null) {
this.$Message.warning("请先点击选择一个部门");
return;
}
this.modalTitle = "添加子部门";
this.showParent = true;
this.formAdd = {
parentId: this.form.id,
sortOrder: 0,
status: 0,
};
this.modalVisible = true;
},
addRoot() {
this.modalTitle = "添加一级部门";
this.showParent = false;
this.formAdd = {
parentId: 0,
sortOrder: 0,
status: 0,
};
this.modalVisible = true;
},
delAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未勾选要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content:
"您确认要删除所选的 " + this.selectCount + " 条数据及其下级所有数据?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteDepartment(ids).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.selectList = [];
this.selectCount = 0;
this.cancelSelect();
this.init();
}
});
},
});
},
},
mounted() {
const height = document.documentElement.clientHeight;
this.maxHeight = Number(height - 287) + "px";
this.init();
},
const loading = ref(true);
const maxHeight = ref("500px");
const strict = ref(true);
const userLoading = ref(false);
const loadingEdit = ref(false);
const modalVisible = ref(false);
const selectList = ref([]);
const selectCount = ref(0);
const showParent = ref(false);
const modalTitle = ref("");
const editTitle = ref("");
const selectedRole = ref([]);
const searchKey = ref("");
const currentNodeKey = ref(null);
const treeProps = {
label: "title",
children: "children",
isLeaf: "isLeaf",
};
const form = ref({
id: "",
title: "",
parentId: "",
parentTitle: "",
sortOrder: 0,
status: 0,
});
const formAdd = ref({});
const formValidate = {
title: [{ required: true, message: "名称不能为空", trigger: "blur" }],
sortOrder: [
{
required: true,
type: "number",
message: "排序值不能为空",
trigger: "blur",
},
],
};
const submitLoading = ref(false);
const data = ref([]);
const dataEdit = ref([]);
const users = ref([]);
function init() {
getParentList();
}
function getParentList() {
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));
}
});
}
function normalizeDepartmentTree(list) {
return list.map((item) => {
const node = { ...item };
if (Array.isArray(node.children) && node.children.length > 0) {
node.children = normalizeDepartmentTree(node.children);
} else {
delete node.children;
}
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;
});
getRoleList({
pageNumber: 1,
pageSize: 10000,
}).then((res) => {
userLoading.value = false;
if (res.success) {
users.value = res.result.records;
form.value = row;
}
});
}
function onCheckChange(_data, { checkedNodes }) {
selectList.value = checkedNodes;
selectCount.value = checkedNodes.length;
}
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 = "";
selectedRole.value = [];
}
function selectTreeEdit(v) {
if (v.length > 0) {
for (const attr in v[0]) {
if (v[0][attr] == null) {
v[0][attr] = "";
}
}
const data = JSON.parse(JSON.stringify(v[0]));
form.value.parentId = data.id;
form.value.parentTitle = data.title;
}
}
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,
});
});
Promise.all([
editDepartment(form.value.id, form.value),
updateDepartmentRole(form.value.id, roleWay),
]).then((res) => {
submitLoading.value = false;
if (res[0].success) {
Message.success("编辑成功");
init();
modalVisible.value = false;
}
});
}
});
}
function submitAdd() {
formAddRef.value.validate((valid) => {
if (valid) {
submitLoading.value = true;
addDepartment(formAdd.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("添加成功");
init();
modalVisible.value = false;
}
});
}
});
}
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) {
Message.warning("您还未勾选要删除的数据");
return;
}
Modal.confirm({
title: "确认删除",
content:
"您确认要删除所选的 " + selectCount.value + " 条数据及其下级所有数据?",
loading: true,
onOk: () => {
let ids = "";
selectList.value.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteDepartment(ids).then((res) => {
Modal.remove();
if (res.success) {
Message.success("删除成功");
selectList.value = [];
selectCount.value = 0;
cancelSelect();
init();
}
});
},
});
}
onMounted(() => {
const height = document.documentElement.clientHeight;
maxHeight.value = Number(height - 287) + "px";
init();
});
</script>
<style lang="scss" scoped>

View File

@@ -7,7 +7,7 @@
</div>
<el-table
ref="table"
ref="tableRef"
v-loading="loading"
border
:data="data"
@@ -56,7 +56,7 @@
:close-on-click-modal="false"
destroy-on-close
>
<el-form ref="roleForm" :model="roleForm" label-width="80px" :rules="roleFormValidate">
<el-form ref="roleFormRef" :model="roleForm" label-width="80px" :rules="roleFormValidate">
<el-form-item label="角色名称" prop="name">
<el-input v-model="roleForm.name" />
</el-form-item>
@@ -81,7 +81,7 @@
>
<div v-loading="treeLoading" style="position: relative; max-height: 560px; overflow: auto">
<el-tree
ref="permTree"
ref="permTreeRef"
:key="permTreeKey"
:data="permData"
:props="{ label: 'title', children: 'children', disabled: 'disabled' }"
@@ -148,376 +148,379 @@
</div>
</template>
<script>
<script setup>
import { nextTick, onMounted, ref } from "vue";
import {
getRoleList,
getRoleList as fetchRoleList,
getAllPermissionList,
addRole,
addRole as addRoleReq,
editRole,
deleteRole,
loadDepartment,
selectRoleMenu,
saveRoleMenu,
} from "@/api/index";
import { Message, Modal } from "@/utils/message";
import util from "@/libs/util.js";
import { useAppStore } from "@/stores/app";
export default {
name: "role-manage",
data() {
return {
superModelLoading: false,
selectIsSuperModel: false,
rolePermsWay: [],
openLevel: "0",
loading: true,
treeLoading: true,
depTreeLoading: true,
submitPermLoading: false,
submitDepLoading: false,
sortColumn: "",
sortType: "desc",
modalType: 0,
roleModalVisible: false,
permModalVisible: false,
depModalVisible: false,
modalTitle: "",
roleForm: {
name: "",
description: "",
},
roleFormValidate: {
name: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
},
submitLoading: false,
selectList: [],
selectCount: 0,
data: [],
pageNumber: 1,
pageSize: 20,
total: 0,
permData: [],
editRolePermId: "",
selectAllFlag: false,
depData: [],
dataType: 0,
editDepartments: [],
saveRoleWay: [],
permTreeKey: 0,
permCheckedKeys: [],
permExpandedKeys: [],
};
},
methods: {
init() {
this.getRoleList();
this.getPermList();
},
changePage() {
this.getRoleList();
this.clearSelectAll();
},
changePageSize() {
this.pageNumber = 1;
this.getRoleList();
},
changeSort(e) {
this.sortColumn = e.prop;
this.sortType = e.order === "ascending" ? "asc" : e.order === "descending" ? "desc" : "";
if (!e.order) {
this.sortType = "";
defineOptions({ name: "role-manage" });
const appStore = useAppStore();
const tableRef = ref(null);
const roleFormRef = ref(null);
const permTreeRef = ref(null);
const superModelLoading = ref(false);
const selectIsSuperModel = ref(false);
const rolePermsWay = ref([]);
const openLevel = ref("0");
const loading = ref(true);
const treeLoading = ref(true);
const depTreeLoading = ref(true);
const submitPermLoading = ref(false);
const submitDepLoading = ref(false);
const sortColumn = ref("");
const sortType = ref("desc");
const modalType = ref(0);
const roleModalVisible = ref(false);
const permModalVisible = ref(false);
const depModalVisible = ref(false);
const modalTitle = ref("");
const roleForm = ref({
name: "",
description: "",
});
const roleFormValidate = {
name: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
};
const submitLoading = ref(false);
const selectList = ref([]);
const selectCount = ref(0);
const data = ref([]);
const pageNumber = ref(1);
const pageSize = ref(20);
const total = ref(0);
const permData = ref([]);
const editRolePermId = ref("");
const selectAllFlag = ref(false);
const depData = ref([]);
const dataType = ref(0);
const editDepartments = ref([]);
const saveRoleWay = ref([]);
const permTreeKey = ref(0);
const permCheckedKeys = ref([]);
const permExpandedKeys = ref([]);
function init() {
getRoleList();
getPermList();
}
function changePage() {
getRoleList();
clearSelectAll();
}
function changePageSize() {
pageNumber.value = 1;
getRoleList();
}
function changeSort(e) {
sortColumn.value = e.prop;
sortType.value = e.order === "ascending" ? "asc" : e.order === "descending" ? "desc" : "";
if (!e.order) {
sortType.value = "";
}
getRoleList();
}
function setRole(val) {
let enable;
val == "onlyView" ? (enable = 0) : (enable = 1);
saveRoleWay.value.map((item) => {
item.isSuper = enable;
});
}
function getRoleList() {
loading.value = true;
let params = {
pageNumber: pageNumber.value,
pageSize: pageSize.value,
sort: sortColumn.value,
order: sortType.value,
};
fetchRoleList(params).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function getPermList() {
treeLoading.value = true;
getAllPermissionList().then((res) => {
if (res.success) {
deleteDisableNode(res.result);
permData.value = res.result;
}
treeLoading.value = false;
});
}
function deleteDisableNode(permData) {
permData.forEach(function (e) {
if (e.status == -1) {
e.title = "[已禁用] " + e.title;
e.disabled = true;
}
if (e.children && e.children.length > 0) {
deleteDisableNode(e.children);
}
});
}
function submitRole() {
roleFormRef.value.validate((valid) => {
if (valid) {
if (modalType.value == 0) {
submitLoading.value = true;
addRoleReq(roleForm.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("操作成功");
getRoleList();
roleModalVisible.value = false;
}
});
} else {
submitLoading.value = true;
roleForm.value.roleId = roleForm.value.id;
editRole(roleForm.value).then((res) => {
submitLoading.value = false;
if (res.success) {
Message.success("操作成功");
getRoleList();
roleModalVisible.value = false;
}
});
}
this.getRoleList();
},
setRole(val) {
let enable;
val == "onlyView" ? (enable = 0) : (enable = 1);
this.saveRoleWay.map((item) => {
item.isSuper = enable;
});
},
getRoleList() {
this.loading = true;
let params = {
pageNumber: this.pageNumber,
pageSize: this.pageSize,
sort: this.sortColumn,
order: this.sortType,
};
getRoleList(params).then((res) => {
this.loading = false;
}
});
}
function addRole() {
modalType.value = 0;
modalTitle.value = "添加角色";
roleForm.value = {
name: "",
description: "",
};
roleModalVisible.value = true;
nextTick(() => {
roleFormRef.value?.clearValidate();
});
}
function edit(v) {
modalType.value = 1;
modalTitle.value = "编辑角色";
roleFormRef.value?.resetFields();
for (let attr in v) {
if (v[attr] == null) {
v[attr] = "";
}
}
let str = JSON.stringify(v);
let roleInfo = JSON.parse(str);
roleForm.value = roleInfo;
roleModalVisible.value = true;
}
function remove(v) {
Modal.confirm({
title: "确认删除",
content: "您确认要删除角色 " + v.name + " ?",
loading: true,
onOk: () => {
deleteRole(v.id).then((res) => {
Modal.remove();
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
Message.success("删除成功");
getRoleList();
}
});
},
getPermList() {
this.treeLoading = true;
getAllPermissionList().then((res) => {
});
}
function clearSelectAll() {
tableRef.value?.clearSelection();
}
function changeSelect(e) {
selectList.value = e;
selectCount.value = e.length;
}
function delAll() {
if (selectCount.value <= 0) {
Message.warning("您还未选择要删除的数据");
return;
}
Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + selectCount.value + " 条数据?",
loading: true,
onOk: () => {
let ids = "";
selectList.value.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteRole(ids).then((res) => {
Modal.remove();
if (res.success) {
this.deleteDisableNode(res.result);
this.permData = res.result;
Message.success("删除成功");
clearSelectAll();
getRoleList();
}
this.treeLoading = false;
});
},
deleteDisableNode(permData) {
let that = this;
permData.forEach(function (e) {
});
}
async function editPerm(v) {
permData.value.map((item) => {
item.children.length != 0
? item.children.map((child) => {
child.children.length != 0
? child.children.map((kid) => {
delete kid.isSuper;
})
: "";
delete child.isSuper;
})
: "";
delete item.isSuper;
});
if (treeLoading.value) {
Message.warning("菜单权限数据加载中,请稍后点击查看");
return;
}
editRolePermId.value = v.id;
modalTitle.value = "分配 " + v.name + " 的菜单权限";
let rolePerms;
let res = await selectRoleMenu(v.id);
if (res.result) {
rolePerms = res.result;
rolePermsWay.value = res.result;
}
permCheckedKeys.value = collectCheckedKeys(permData.value, rolePerms);
permExpandedKeys.value = computeExpandedKeys(openLevel.value);
permTreeKey.value += 1;
permModalVisible.value = true;
}
function collectCheckedKeys(permData, rolePerms) {
const keys = [];
const walk = (nodes) => {
nodes.forEach((p) => {
if (hasPerm(p, rolePerms) && p.status != -1) {
if (p.children && p.children.length === 0) {
keys.push(p.id);
}
}
if (p.children && p.children.length > 0) {
walk(p.children);
}
});
};
walk(permData);
return keys;
}
function hasPerm(p, rolePerms) {
if (!rolePerms) return false;
let flag = false;
for (let i = 0; i < rolePerms.length; i++) {
if (p.id == rolePerms[i].menuId) {
p.isSuper = rolePerms[i].isSuper;
flag = true;
break;
}
}
return flag;
}
function submitPermEdit() {
saveRoleWay.value = [];
selectIsSuperModel.value = true;
const tree = permTreeRef.value;
const selectedNodes = [
...tree.getCheckedNodes(false, true),
];
let way = [];
selectedNodes.forEach((e) => {
let perm = {
title: e.title,
isSuper: e.isSuper ? 1 : 0,
menuId: e.id,
roleId: editRolePermId.value,
};
way.push(perm);
saveRoleWay.value = way;
});
}
function saveRole() {
superModelLoading.value = true;
saveRoleMenu(editRolePermId.value, saveRoleWay.value).then((res) => {
superModelLoading.value = false;
if (res.success) {
Message.success("操作成功");
appStore.setAdded(false);
util.initRouter();
getRoleList();
permModalVisible.value = false;
selectIsSuperModel.value = false;
}
});
}
function loadData(item, callback) {
loadDepartment(item.id, { openDataFilter: false }).then((res) => {
if (res.success) {
res.result.forEach(function (e) {
e.checked = false;
if (e.isParent) {
e.loading = false;
e.children = [];
}
if (e.status == -1) {
e.title = "[已禁用] " + e.title;
e.disabled = true;
}
if (e.children && e.children.length > 0) {
that.deleteDisableNode(e.children);
}
});
},
submitRole() {
this.$refs.roleForm.validate((valid) => {
if (valid) {
if (this.modalType == 0) {
this.submitLoading = true;
addRole(this.roleForm).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getRoleList();
this.roleModalVisible = false;
}
});
} else {
this.submitLoading = true;
this.roleForm.roleId = this.roleForm.id;
editRole(this.roleForm).then((res) => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getRoleList();
this.roleModalVisible = false;
}
});
}
}
});
},
addRole() {
this.modalType = 0;
this.modalTitle = "添加角色";
this.roleForm = {
name: "",
description: "",
};
this.roleModalVisible = true;
this.$nextTick(() => {
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] = "";
}
callback(res.result);
}
});
}
function computeExpandedKeys(level) {
const keys = [];
const walk = (nodes, depth) => {
nodes.forEach((n) => {
if (level === "0") {
keys.push(n.id);
} else if (level === "2" && depth < 1) {
keys.push(n.id);
} else if (level === "3" && depth < 2) {
keys.push(n.id);
}
let str = JSON.stringify(v);
let roleInfo = JSON.parse(str);
this.roleForm = roleInfo;
this.roleModalVisible = true;
},
remove(v) {
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除角色 " + v.name + " ?",
loading: true,
onOk: () => {
deleteRole(v.id).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.getRoleList();
}
});
},
});
},
clearSelectAll() {
this.$refs.table?.clearSelection();
},
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
},
delAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
if (n.children && n.children.length) {
walk(n.children, depth + 1);
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectCount + " 条数据?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
deleteRole(ids).then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("删除成功");
this.clearSelectAll();
this.getRoleList();
}
});
},
});
},
async editPerm(v) {
this.permData.map((item) => {
item.children.length != 0
? item.children.map((child) => {
child.children.length != 0
? child.children.map((kid) => {
delete kid.isSuper;
})
: "";
delete child.isSuper;
})
: "";
delete item.isSuper;
});
});
};
if (level !== "1") {
walk(permData.value, 0);
}
return keys;
}
function changeOpen(v) {
permExpandedKeys.value = computeExpandedKeys(v);
permTreeKey.value += 1;
}
if (this.treeLoading) {
this.$Message.warning("菜单权限数据加载中,请稍后点击查看");
return;
}
this.editRolePermId = v.id;
this.modalTitle = "分配 " + v.name + " 的菜单权限";
let rolePerms;
let res = await selectRoleMenu(v.id);
if (res.result) {
rolePerms = res.result;
this.rolePermsWay = res.result;
}
this.permCheckedKeys = this.collectCheckedKeys(this.permData, rolePerms);
this.permExpandedKeys = this.computeExpandedKeys(this.openLevel);
this.permTreeKey += 1;
this.permModalVisible = true;
},
collectCheckedKeys(permData, rolePerms) {
const keys = [];
const walk = (nodes) => {
nodes.forEach((p) => {
if (this.hasPerm(p, rolePerms) && p.status != -1) {
if (p.children && p.children.length === 0) {
keys.push(p.id);
}
}
if (p.children && p.children.length > 0) {
walk(p.children);
}
});
};
walk(permData);
return keys;
},
hasPerm(p, rolePerms) {
if (!rolePerms) return false;
let flag = false;
for (let i = 0; i < rolePerms.length; i++) {
if (p.id == rolePerms[i].menuId) {
p.isSuper = rolePerms[i].isSuper;
flag = true;
break;
}
}
return flag;
},
submitPermEdit() {
this.saveRoleWay = [];
this.selectIsSuperModel = true;
const tree = this.$refs.permTree;
const selectedNodes = [
...tree.getCheckedNodes(false, true),
];
let way = [];
selectedNodes.forEach((e) => {
let perm = {
title: e.title,
isSuper: e.isSuper ? 1 : 0,
menuId: e.id,
roleId: this.editRolePermId,
};
way.push(perm);
this.saveRoleWay = way;
});
},
saveRole() {
this.superModelLoading = true;
saveRoleMenu(this.editRolePermId, this.saveRoleWay).then((res) => {
this.superModelLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.$store.commit("setAdded", false);
util.initRouter(this);
this.getRoleList();
this.permModalVisible = false;
this.selectIsSuperModel = false;
}
});
},
loadData(item, callback) {
loadDepartment(item.id, { openDataFilter: false }).then((res) => {
if (res.success) {
res.result.forEach(function (e) {
e.checked = false;
if (e.isParent) {
e.loading = false;
e.children = [];
}
if (e.status == -1) {
e.title = "[已禁用] " + e.title;
e.disabled = true;
}
});
callback(res.result);
}
});
},
computeExpandedKeys(level) {
const keys = [];
const walk = (nodes, depth) => {
nodes.forEach((n) => {
if (level === "0") {
keys.push(n.id);
} else if (level === "2" && depth < 1) {
keys.push(n.id);
} else if (level === "3" && depth < 2) {
keys.push(n.id);
}
if (n.children && n.children.length) {
walk(n.children, depth + 1);
}
});
};
if (level !== "1") {
walk(this.permData, 0);
}
return keys;
},
changeOpen(v) {
this.permExpandedKeys = this.computeExpandedKeys(v);
this.permTreeKey += 1;
},
},
mounted() {
this.init();
},
};
onMounted(() => {
init();
});
</script>
<style lang="scss" scoped>
.role-list {

View File

@@ -517,15 +517,17 @@
</template>
</el-dialog>
<hotzone ref="hotzone" @changeZone="changeZone"></hotzone>
<hotzone ref="hotzoneRef" @changeZone="changeZone"></hotzone>
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManage" />
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManageRef" />
</el-dialog>
</div>
</template>
<script>
<script setup>
import { ref, watch, nextTick } from "vue";
import { CircleClose } from "@element-plus/icons-vue";
import { Message } from "@/utils/message";
import alignTextLeftImg from "@/assets/align-text-left.png";
import alignTextCenterImg from "@/assets/align-text-center.png";
import alignTextRightImg from "@/assets/align-text-right.png";
@@ -534,303 +536,295 @@ import { modelData } from "./config";
import hotzone from "@/views/shop/hotzone";
import ways from "@/views/lili-dialog/wap.js";
import categoryTemplate from "@/views/lili-dialog/template/category";
export default {
components: {
ossManage,
hotzone,
categoryTemplate,
CircleClose,
},
data() {
const props = defineProps(["res"]);
const emit = defineEmits(["handleDrawer"]);
// alignTextLeftImg/alignTextCenterImg/alignTextRightImg、ways(选择链接的类型)、modelData(装修数据) 为 import 常量,模板中直接使用
const picModelFlag = ref(false); //图片选择器
const linkType = ref("goods"); // dialog弹窗口类型
const styleFlag = ref(false); //广告魔方开关
const textAlign = ref(
props.res.options.list[0] ? props.res.options.list[0].textAlign : "center"
); //文字对齐方式
const promotionsFlag = ref(false); //广告魔方开关
const selectedLinkIndex = ref(""); //选择链接的索引
const selectedGoods = ref(""); // 已选商品
const selectedLinks = ref(""); // 已选链接
const modelList = ref(""); // 装修列表
const enableSelectCategory = ref(false); //商品是否绑定分类
const pendingCategory = ref(null); // 选择分类弹窗草稿
const goodsSelectedIndex = ref(0); //绑定商品分类的索引
// hotzoneRef/ossManageRef:模板 ref 与组件 import 同名,改名避免互相覆盖
const liliDialog = ref(null);
const hotzoneRef = ref(null);
const ossManageRef = ref(null);
watch(
() => props.res,
(val) => {},
{ deep: true }
);
// 选择分类(弹窗内暂存,确定后写回)
function onCategorySelected(val) {
pendingCategory.value = val;
}
function handleCancelCategoryModal() {
pendingCategory.value = null;
enableSelectCategory.value = false;
}
function handleConfirmCategoryModal() {
if (pendingCategory.value?.length) {
confirmCategory(pendingCategory.value);
}
pendingCategory.value = null;
enableSelectCategory.value = false;
}
function confirmCategory(val) {
let data = {
...props.res.options.list[0].titleWay[goodsSelectedIndex.value],
};
let callback = {
id: val[0].id,
name: val[0].name,
categoryIdWay: val[0].id,
};
data = {
...data,
bindCategory: callback,
};
props.res.options.list[0].listWay = props.res.options.list[0].listWay.filter(
(item) => {
return item.___index != goodsSelectedIndex.value;
}
);
props.res.options.list[0].titleWay[goodsSelectedIndex.value] = data;
console.log(props.res.options.list[0]);
}
// 商品排序
function slotGoods(list, key, val) {
const newVal = [];
let newValIndex = 0;
// 给当前点击的商品分组
list.forEach((item, index) => {
if (item.___index == key) {
newVal.push(item);
}
});
// 获得当前点击商品的索引
newVal.forEach((item, index) => {
if (item.id == val.id) {
newValIndex = index;
}
});
// 进行商品排序
upData(newVal, newValIndex);
if (list.length == newVal.length) {
list = newVal;
} else {
let newList;
newVal.forEach((item, index) => {
newList = list.filter((child) => {
return child.id != item.id && child.___index != key;
});
});
list = [...newList, ...newVal];
}
props.res.options.list[0]["listWay"] = list;
}
// 轮播图排序
function slotBanner(val, key, index, down) {
console.log(val);
if (down == "down") {
downData(val.options.list, index);
} else {
upData(val.options.list, index);
}
}
function upData(arr, index) {
let newArr = [];
if (arr.length > 1 && index !== 0) {
newArr = swapItems(arr, index, index - 1);
}
return newArr;
}
function swapItems(arr, index1, index2) {
arr[index1] = arr.splice(index2, 1, arr[index1])[0];
return arr;
}
function downData(arr, index) {
let newArr = [];
if (arr.length > 1 && index !== arr.length - 1) {
newArr = swapItems(arr, index, index + 1);
}
return newArr;
}
// 改变横纵切换title内容
function changeDirection(val, data) {
if (val == "horizontal") {
const props = { ...data };
data.title = [];
data.title.push(props.title[0]);
}
}
// 选择风格
function selectStyle() {
styleFlag.value = !styleFlag.value;
}
function selectPromotions() {
promotionsFlag.value = !promotionsFlag.value;
}
// 回调选择的链接
function selectedLink(val) {
selectedLinks.value.zoneInfo = [];
delete val.selected;
delete val.intro;
delete val.mobileIntro;
selectedLinks.value.url = val;
}
// 回调的商品信息
function selectedGoodsData(val) {
if (!val) return false;
let data = val.map((item) => {
delete item.selected;
delete item.intro;
delete item.mobileIntro;
return {
alignTextLeftImg,
alignTextCenterImg,
alignTextRightImg,
ways, // 选择链接的类型
picModelFlag: false, //图片选择器
linkType: "goods", // dialog弹窗口类型
styleFlag: false, //广告魔方开关
textAlign: this.res.options.list[0]
? this.res.options.list[0].textAlign
: "center", //文字对齐方式
promotionsFlag: false, //广告魔方开关
selectedLinkIndex: "", //选择链接的索引
modelData, // 装修数据
selectedGoods: "", // 已选商品
selectedLinks: "", // 已选链接
modelList: "", // 装修列表
enableSelectCategory: false, //商品是否绑定分类
pendingCategory: null, // 选择分类弹窗草稿
goodsSelectedIndex: 0, //绑定商品分类的索引
img: item.thumbnail,
title: item.goodsName,
type: selectedGoods.value.title,
___index: selectedGoods.value.___index,
...item,
};
},
watch: {
res: {
handler(val) {},
deep: true,
},
},
props: ["res"],
methods: {
// 选择分类(弹窗内暂存,确定后写回)
onCategorySelected(val) {
this.pendingCategory = val;
},
handleCancelCategoryModal() {
this.pendingCategory = null;
this.enableSelectCategory = false;
},
handleConfirmCategoryModal() {
if (this.pendingCategory?.length) {
this.confirmCategory(this.pendingCategory);
}
this.pendingCategory = null;
this.enableSelectCategory = false;
},
confirmCategory(val) {
let data = {
...this.res.options.list[0].titleWay[this.goodsSelectedIndex],
};
let callback = {
id: val[0].id,
name: val[0].name,
categoryIdWay: val[0].id,
};
data = {
...data,
bindCategory: callback,
};
this.res.options.list[0].listWay =
this.res.options.list[0].listWay.filter((item) => {
return item.___index != this.goodsSelectedIndex;
});
this.res.options.list[0].titleWay[this.goodsSelectedIndex] = data;
});
props.res.options.list[0].listWay.push(...data);
// 清除已经绑定的分类
props.res.options.list[0].titleWay[goodsSelectedIndex.value].bindCategory =
"";
linkType.value = "";
}
// 绑定商品
function bindGoodsId(val, index) {
selectedGoods.value = val;
goodsSelectedIndex.value = index;
liliDialogFlag(true);
}
// 绑定分类
function bindGoodsCategory(index, key) {
pendingCategory.value = null;
enableSelectCategory.value = true;
goodsSelectedIndex.value = index;
}
// 点击抽屉
function clickDrawer(item, index) {
emit("handleDrawer", item);
styleFlag.value = false;
promotionsFlag.value = false;
}
// 打开图片选择器
function liliDialogFlag(flag) {
liliDialog.value.clearGoodsSelected();
liliDialog.value.goodsFlag = flag;
liliDialog.value.flag = true;
}
console.log(this.res.options.list[0]);
},
// 商品排序
slotGoods(list, key, val) {
const newVal = [];
let newValIndex = 0;
// 给当前点击的商品分组
list.forEach((item, index) => {
if (item.___index == key) {
newVal.push(item);
}
function changeTextAlign(val) {
props.res.options.list[0].textAlign = val;
textAlign.value = val;
}
// 点击链接赋值一个唯一值,并将当前选择的模块赋值
function clickLink(val, index, oval) {
selectedLinks.value = val;
if (val.model === "hotzone") {
if (!val.zoneInfo) {
val.zoneInfo = [];
}
hotzoneRef.value.open(val);
} else {
liliDialogFlag(false);
}
}
function addZone(zoneInfo) {
selectedLinks.value.zoneInfo.push(zoneInfo);
}
function changeZone(zoneInfo) {
selectedLinks.value.zoneInfo = zoneInfo;
}
//点击图片解析成base64
function changeFile(item, index) {
const file = document.getElementById("files" + index).files[0];
if (file == void 0) return false;
const reader = new FileReader();
reader.readAsDataURL(file);
nextTick((res) => {
reader.onload = (e) => {
item.img = e.target.result;
};
});
}
//添加设置
function addDecorate(type, data) {
if (type === "notice") {
if (data.options.list[0].direction == "vertical") {
props.res.options.list[0].title.push({
content: "",
});
// 获得当前点击商品的索引
newVal.forEach((item, index) => {
if (item.id == val.id) {
newValIndex = index;
}
});
// 进行商品排序
this.upData(newVal, newValIndex);
if (list.length == newVal.length) {
list = newVal;
} else {
let newList;
newVal.forEach((item, index) => {
newList = list.filter((child) => {
return child.id != item.id && child.___index != key;
});
});
list = [...newList, ...newVal];
}
this.res.options.list[0]["listWay"] = list;
},
// 轮播图排序
slotBanner(val, key, index, down) {
console.log(val);
if (down == "down") {
this.downData(val.options.list, index);
} else {
this.upData(val.options.list, index);
}
},
upData(arr, index) {
let newArr = [];
if (arr.length > 1 && index !== 0) {
newArr = this.swapItems(arr, index, index - 1);
}
return newArr;
},
swapItems(arr, index1, index2) {
arr[index1] = arr.splice(index2, 1, arr[index1])[0];
return arr;
},
downData(arr, index) {
let newArr = [];
if (arr.length > 1 && index !== arr.length - 1) {
newArr = this.swapItems(arr, index, index + 1);
}
return newArr;
},
// 改变横纵切换title内容
changeDirection(val, data) {
if (val == "horizontal") {
const props = { ...data };
data.title = [];
data.title.push(props.title[0]);
}
},
// 选择风格
selectStyle() {
this.styleFlag = !this.styleFlag;
},
selectPromotions() {
this.promotionsFlag = !this.promotionsFlag;
},
// 回调选择的链接
selectedLink(val) {
this.selectedLinks.zoneInfo = [];
delete val.selected;
delete val.intro;
delete val.mobileIntro;
this.selectedLinks.url = val;
},
// 回调的商品信息
selectedGoodsData(val) {
if (!val) return false;
let data = val.map((item) => {
delete item.selected;
delete item.intro;
delete item.mobileIntro;
return {
img: item.thumbnail,
title: item.goodsName,
type: this.selectedGoods.title,
___index: this.selectedGoods.___index,
...item,
};
});
this.res.options.list[0].listWay.push(...data);
// 清除已经绑定的分类
this.res.options.list[0].titleWay[this.goodsSelectedIndex].bindCategory =
"";
this.linkType = "";
},
// 绑定商品
bindGoodsId(val, index) {
this.selectedGoods = val;
this.goodsSelectedIndex = index;
this.liliDialogFlag(true);
},
// 绑定分类
bindGoodsCategory(index, key) {
this.pendingCategory = null;
this.enableSelectCategory = true;
this.goodsSelectedIndex = index;
},
// 点击抽屉
clickDrawer(item, index) {
this.$emit("handleDrawer", item);
this.styleFlag = false;
this.promotionsFlag = false;
},
// 打开图片选择器
liliDialogFlag(flag) {
this.$refs.liliDialog.clearGoodsSelected();
this.$refs.liliDialog.goodsFlag = flag;
this.$refs.liliDialog.flag = true;
},
changeTextAlign(val) {
this.res.options.list[0].textAlign = val;
this.textAlign = val;
},
// 点击链接赋值一个唯一值,并将当前选择的模块赋值
clickLink(val, index, oval) {
this.selectedLinks = val;
if (val.model === "hotzone") {
if (!val.zoneInfo) {
val.zoneInfo = [];
}
this.$refs.hotzone.open(val);
} else {
this.liliDialogFlag(false);
}
},
addZone(zoneInfo) {
this.selectedLinks.zoneInfo.push(zoneInfo);
},
changeZone(zoneInfo) {
this.selectedLinks.zoneInfo = zoneInfo;
},
//点击图片解析成base64
changeFile(item, index) {
const file = document.getElementById("files" + index).files[0];
if (file == void 0) return false;
const reader = new FileReader();
reader.readAsDataURL(file);
this.$nextTick((res) => {
reader.onload = (e) => {
item.img = e.target.result;
};
});
},
//添加设置
addDecorate(type, data) {
if (type === "notice") {
if (data.options.list[0].direction == "vertical") {
this.res.options.list[0].title.push({
content: "",
});
} else {
this.$Message.error("仅纵向支持多添加");
}
} else {
let way = {
img: "https://picsum.photos/id/264/200/200",
title: "标题",
link: "",
url: "",
size: this.res.options.list[0] ? this.res.options.list[0].size : "",
model: "link",
};
this.res.options.list.push(way);
}
},
addHotPoint() {
let way = {
img: "https://picsum.photos/id/264/200/200",
text: "标题",
link: "",
url: "",
};
this.res.options.list[0].points.push(way);
},
// 图片选择器回显
callbackSelected(val) {
this.picModelFlag = false;
if (!val?.url) return;
this.selectedGoods.img = val.url;
},
// 点击选择图片
handleClickFile(item, index) {
this.selectedGoods = item;
this.picModelFlag = true;
this.$nextTick(() => {
if (this.$refs.ossManage) {
this.$refs.ossManage.selectImage = true;
}
});
},
removeNotice(index) {
this.$nextTick(() => {
this.res.options.list[0].title.splice(index, 1);
});
},
// 关闭
closeDecorate(index) {
this.$nextTick(() => {
this.res.options.list.splice(index, 1);
});
},
},
};
} else {
Message.error("仅纵向支持多添加");
}
} else {
let way = {
img: "https://picsum.photos/id/264/200/200",
title: "标题",
link: "",
url: "",
size: props.res.options.list[0] ? props.res.options.list[0].size : "",
model: "link",
};
props.res.options.list.push(way);
}
}
function addHotPoint() {
let way = {
img: "https://picsum.photos/id/264/200/200",
text: "标题",
link: "",
url: "",
};
props.res.options.list[0].points.push(way);
}
// 图片选择器回显
function callbackSelected(val) {
picModelFlag.value = false;
if (!val?.url) return;
selectedGoods.value.img = val.url;
}
// 点击选择图片
function handleClickFile(item, index) {
selectedGoods.value = item;
picModelFlag.value = true;
nextTick(() => {
if (ossManageRef.value) {
ossManageRef.value.selectImage = true;
}
});
}
function removeNotice(index) {
nextTick(() => {
props.res.options.list[0].title.splice(index, 1);
});
}
// 关闭
function closeDecorate(index) {
nextTick(() => {
props.res.options.list.splice(index, 1);
});
}
</script>
<style scoped lang="scss">
@import "./decorate.scss";

View File

@@ -74,162 +74,158 @@
</div>
</div>
</template>
<script>
<script setup>
import { ref, watch, onMounted, nextTick } from "vue";
import { useRoute } from "vue-router";
import { CircleClose } from "@element-plus/icons-vue";
import templates from "./template/index";
import Draggable from "vuedraggable";
import { modelData } from "./config";
import decorate from "./decorate";
import * as API_Other from "@/api/other";
export default {
components: {
Draggable,
decorate,
CircleClose,
},
data() {
return {
templates, // 模板类型
modelData, // 装修模型
qrcode: "", // 二维码
selected: 0, // 已选下标
contentData: {
// 总数据
list: [],
},
decorateData: "", // 装修数据
decoratePromotionsData: "", // 装修数据
};
},
watch: {
contentData: {
handler(val) {
this.$store.state.styleStore = val;
},
deep: true,
},
},
mounted() {
this.init();
import { getStore } from "@/libs/storage";
import { Modal } from "@/utils/message";
import { useAppStore } from "@/stores/app";
const route = useRoute();
const appStore = useAppStore();
// templates: 模板类型,modelData: 装修模型,均为 import 常量,模板中直接使用
const qrcode = ref(""); // 二维码
const selected = ref(0); // 已选下标
const contentData = ref({
// 总数据
list: [],
});
const decorateData = ref(""); // 装修数据
const decoratePromotionsData = ref(""); // 装修数据
watch(
contentData,
(val) => {
appStore.styleStore = val;
},
{ deep: true }
);
methods: {
getModelKey(model) {
return model.type || model.name;
},
getContentItemKey(element) {
return element.key || element.model || element.type;
},
cloneModel(model) {
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
const cloned = JSON.parse(JSON.stringify(model));
return {
...cloned,
key,
model: cloned.type + "_" + key,
};
},
// 初始化数据
init() {
// 先读缓存,如果缓存有值则读缓存。
const cache = this.getStore('managerMobilePageCache')
if(cache){
this.$Modal.confirm({
title: '提示',
content: '获取到本地有缓存数据,是否使用缓存数据?',
okText: '使用',
cancelText: '取消',
onOk: () => {
const data = JSON.parse(cache);
this.contentData = data;
}
});
onMounted(() => {
init();
});
}
if (!this.$route.query.id) return false;
function getModelKey(model) {
return model.type || model.name;
}
function getContentItemKey(element) {
return element.key || element.model || element.type;
}
function cloneModel(model) {
const key = Date.now() + "_" + Math.ceil(Math.random() * 99999);
const cloned = JSON.parse(JSON.stringify(model));
return {
...cloned,
key,
model: cloned.type + "_" + key,
};
}
// 初始化数据
function init() {
// 先读缓存,如果缓存有值则读缓存。
const cache = getStore('managerMobilePageCache')
if(cache){
Modal.confirm({
title: '提示',
content: '获取到本地有缓存数据,是否使用缓存数据?',
okText: '使用',
cancelText: '取消',
onOk: () => {
const data = JSON.parse(cache);
contentData.value = data;
}
});
API_Other.getHomeData(this.$route.query.id).then((res) => {
this.contentData = JSON.parse(res.result.pageData);
}
if (!route.query.id) return false;
this.handleComponent(this.contentData.list[0], 0);
});
API_Other.getHomeData(route.query.id).then((res) => {
contentData.value = JSON.parse(res.result.pageData);
handleComponent(contentData.value.list[0], 0);
});
}
// 中间组件拖动,右侧数据绑定不变
function handleContentlEnd(evt) {
const { newIndex } = evt;
handleComponent(contentData.value.list[newIndex], newIndex);
}
// 关闭楼层装修
function closeComponent(index) {
nextTick(() => {
decorateData.value = "";
// 如果当前楼层不为一
if (contentData.value.list.length > 1) {
// 如果当前最底层 给下一层赋值
if (index - 1 == -1) {
handleComponent(contentData.value.list[index], index);
} else {
// 如果不是最底层给上一层赋值
handleComponent(contentData.value.list[index - 1], index - 1);
}
contentData.value.list.splice(index, 1);
} else {
contentData.value.list.splice(index, 1);
}
});
}
// 点击楼层装修
function handleComponent(val, index) {
selected.value = index;
decorateData.value = val;
}
// 右侧栏回调
function handleDrawer(val) {
const newIndex = selected.value;
decorateData.value = "";
contentData.value.list[newIndex] = {
...val,
options: {
...val.options,
},
model: val.type,
};
contentData.value = JSON.parse(JSON.stringify(contentData.value));
decorateData.value = contentData.value.list[newIndex];
}
// 中间组件拖动,右侧数据绑定不变
handleContentlEnd(evt) {
const { newIndex } = evt;
this.handleComponent(this.contentData.list[newIndex], newIndex);
// 封装拖拽参数(原名 package,ESM 严格模式下为保留字,改名 packageModel)
function packageModel(val, newIndex) {
contentData.value.list[newIndex] = "";
val = JSON.parse(JSON.stringify(val));
const key = val.key || Date.now() + "_" + Math.ceil(Math.random() * 99999);
contentData.value.list[newIndex] = {
...val,
options: {
...val.options,
},
key,
model: val.model || val.type + "_" + key,
};
}
// 拖动
function handleContentlAdd(evt) {
const { newIndex } = evt;
// 关闭楼层装修
closeComponent(index) {
this.$nextTick(() => {
this.decorateData = "";
// 如果当前楼层不为一
if (this.contentData.list.length > 1) {
// 如果当前最底层 给下一层赋值
if (index - 1 == -1) {
this.handleComponent(this.contentData.list[index], index);
} else {
// 如果不是最底层给上一层赋值
this.handleComponent(this.contentData.list[index - 1], index - 1);
}
this.contentData.list.splice(index, 1);
} else {
this.contentData.list.splice(index, 1);
}
});
},
// 点击楼层装修
handleComponent(val, index) {
this.selected = index;
this["decorateData"] = val;
},
// 右侧栏回调
handleDrawer(val) {
const newIndex = this.selected;
this.decorateData = "";
this.contentData.list[newIndex] = {
...val,
options: {
...val.options,
},
model: val.type,
};
this.contentData.list = JSON.parse(JSON.stringify(this.contentData.list));
this.decorateData = this.contentData.list[newIndex];
},
// 封装拖拽参数
package(val, newIndex) {
this.contentData.list[newIndex] = "";
val = JSON.parse(JSON.stringify(val));
const key = val.key || Date.now() + "_" + Math.ceil(Math.random() * 99999);
this.contentData.list[newIndex] = {
...val,
options: {
...val.options,
},
key,
model: val.model || val.type + "_" + key,
};
},
// 拖动
handleContentlAdd(evt) {
const { newIndex } = evt;
this.package(this.contentData.list[newIndex], newIndex);
this.handleComponent(this.contentData.list[newIndex], newIndex);
},
handleMove() {
return true;
},
},
};
packageModel(contentData.value.list[newIndex], newIndex);
handleComponent(contentData.value.list[newIndex], newIndex);
}
function handleMove() {
return true;
}
</script>
<style scoped lang="scss">
@import "./style.scss";

View File

@@ -6,31 +6,25 @@
<component :is="layout[name]"></component>
</div>
</template>
<script>
import layout from "./index";
<script setup>
import { onMounted, ref } from "vue";
import { useRoute } from "vue-router";
import layout from "./index"; // 装修模块
import navbar from "./navbar";
export default {
components: {
navbar
},
data() {
return {
layout, // 装修模块
name: "index", // 装修的页面
pagetype: "INDEX",
};
},
mounted() {
this.pagetype = this.$route.query.pagetype || "INDEX";
},
methods: {
selected(val) {
// 顶部栏点击切换
this.name = val;
}
}
};
const route = useRoute();
const name = ref("index"); // 装修的页面
const pagetype = ref("INDEX");
onMounted(() => {
pagetype.value = route.query.pagetype || "INDEX";
});
function selected(val) {
// 顶部栏点击切换
name.value = val;
}
</script>
<style scoped lang="scss">
.box {

View File

@@ -56,203 +56,208 @@
</div>
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useAppStore } from "@/stores/app";
import { Message } from "@/utils/message";
import { getStore, setStore } from "@/libs/storage";
import * as API_Other from "@/api/other.js";
export default {
props: ["pagetype"],
data() {
return {
hasCache:false, // 是否有缓存
progress: true, // 展示进度
num: 20, // 提交进度
saveDialog: false, // 加载状态
way: [
{
title: "首页",
name: "index",
selected: true,
},
],
const props = defineProps(["pagetype"]);
const emit = defineEmits(["selected"]);
submitWay: {
// 表单信息
pageShow: this.$route.query.type || false,
name: this.$route.query.name || "模板名称",
pageClientType: "H5"
}
};
const route = useRoute();
const router = useRouter();
const appStore = useAppStore();
const hasCache = ref(false); // 是否有缓存
const progress = ref(true); // 展示进度
const num = ref(20); // 提交进度
const saveDialog = ref(false); // 加载状态
const way = ref([
{
title: "首页",
name: "index",
selected: true,
},
watch: {
pagetype: {
handler(val) {
this.way.length = 0;
if (val == "INDEX") {
this.way.push({ title: "首页", name: "index", selected: true });
} else if (val == "SPECIAL") {
this.way.push({ title: "专题", name: "special", selected: true });
}
},
immediate: true,
},
},
mounted() {
this.hasCache = this.getStore('managerMobilePageCache') ? true : false;
},
methods: {
clearCache(){
this.setStore('managerMobilePageCache','');
this.$Message.success('清空成功')
},
// 将楼层装修的内容写入到本地缓存中
witeLocalStore(){
this.setStore('managerMobilePageCache', this.$store.state.styleStore)
this.$Message.success('写入成功')
},
]);
clickBtn(val) {
this.way.forEach((item, index) => {
item.selected = false;
});
val.selected = true;
this.$emit("selected", val.name);
},
const submitWay = reactive({
// 表单信息
pageShow: route.query.type || false,
name: route.query.name || "模板名称",
pageClientType: "H5"
});
/**
* 加载,并保存模板
*/
handleSpinShow() {
this.saveDialog = true;
},
// 填写是否发布,模板名称之后保存
save() {
if (
this.$store.state.styleStore == void 0 &&
this.$route.query.pagetype != 'SPECIAL'
) {
this.$Message.error("请装修楼层");
return false;
}
this.submitWay?.pageShow === true
? (this.submitWay.pageShow = "OPEN")
: (this.submitWay.pageShow = "CLOSE");
this.submitWay.pageData = JSON.stringify(this.$store.state.styleStore);
this.submitWay.pageType = this.$route.query.pagetype || "INDEX";
this.$route.query.id ? this.updateHome() : this.submit(this.submitWay);
},
// 更新
updateHome() {
this.progress = false;
API_Other.updateHome(this.$route.query.id, {
pageData: JSON.stringify(this.$store.state.styleStore),
name: this.submitWay.name,
pageShow: this.submitWay.pageShow,
pageType: this.submitWay.pageType,
pageClientType: "H5",
})
.then(res => {
this.num = 50;
if (res.success) {
this.num = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
this.saveDialog = false;
this.$Message.success("修改成功");
this.goBack();
}, 1000);
} else {
this.saveDialog = false;
this.$Message.error("修改失败,请稍后重试");
}
console.log(res);
})
.catch(error => {});
},
// 更新
update(submitWay) {
console.log(this.$store.state.openStyleStore[0], "123123123");
if (this.$store.state.openStyleStore == void 0) {
this.$Message.error("请装修楼层!");
return false;
}
this.progress = false;
let id = this.$route.query.id;
const pagetype = this.$route.query.pagetype;
console.log(this.$store.state.openStyleStore, submitWay);
const pageType = {
INDEX: "INDEX",
ALERT: "OPEN_SCREEN_PAGE",
OPEN_SCREEN_ANIMATION: "OPEN_SCREEN_ANIMATION",
}[pagetype ? pagetype : "INDEX"];
if (pagetype) {
submitWay.pageData = JSON.stringify(
this.$store.state.openStyleStore[0]
);
submitWay.pageType = pageType;
id = this.$store.state.openStoreId;
}
API_Other.updateHome(id, submitWay)
.then((res) => {
this.num = 50;
if (res.success) {
this.num = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
this.saveDialog = false;
this.$Message.success("修改成功");
this.goBack();
}, 1000);
} else {
this.saveDialog = false;
this.$Message.error("修改失败,请稍后重试");
}
console.log(res);
})
.catch((error) => {});
},
// 返回查询数据页面
goBack() {
this.$router.go(-1);
},
// 保存
submit(submitWay) {
this.progress = false;
API_Other.setHomeSetup(submitWay)
.then(res => {
this.num = 50;
if (res.success) {
this.num = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
this.saveDialog = false;
this.$Message.success("保存成功");
this.goBack();
}, 1000);
} else {
this.progress = true;
this.saveDialog = false;
this.$Message.error("保存失败,请稍后重试");
}
console.log(res);
})
.catch(error => {});
watch(
() => props.pagetype,
(val) => {
way.value.length = 0;
if (val == "INDEX") {
way.value.push({ title: "首页", name: "index", selected: true });
} else if (val == "SPECIAL") {
way.value.push({ title: "专题", name: "special", selected: true });
}
},
{ immediate: true }
);
onMounted(() => {
hasCache.value = getStore('managerMobilePageCache') ? true : false;
});
function clearCache() {
setStore('managerMobilePageCache','');
Message.success('清空成功')
}
// 将楼层装修的内容写入到本地缓存中
function witeLocalStore() {
setStore('managerMobilePageCache', appStore.styleStore)
Message.success('写入成功')
}
function clickBtn(val) {
way.value.forEach((item, index) => {
item.selected = false;
});
val.selected = true;
emit("selected", val.name);
}
/**
* 加载,并保存模板
*/
function handleSpinShow() {
saveDialog.value = true;
}
// 填写是否发布,模板名称之后保存
function save() {
if (
appStore.styleStore == void 0 &&
route.query.pagetype != 'SPECIAL'
) {
Message.error("请装修楼层");
return false;
}
};
submitWay?.pageShow === true
? (submitWay.pageShow = "OPEN")
: (submitWay.pageShow = "CLOSE");
submitWay.pageData = JSON.stringify(appStore.styleStore);
submitWay.pageType = route.query.pagetype || "INDEX";
route.query.id ? updateHome() : submit(submitWay);
}
// 更新
function updateHome() {
progress.value = false;
API_Other.updateHome(route.query.id, {
pageData: JSON.stringify(appStore.styleStore),
name: submitWay.name,
pageShow: submitWay.pageShow,
pageType: submitWay.pageType,
pageClientType: "H5",
})
.then(res => {
num.value = 50;
if (res.success) {
num.value = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
saveDialog.value = false;
Message.success("修改成功");
goBack();
}, 1000);
} else {
saveDialog.value = false;
Message.error("修改失败,请稍后重试");
}
console.log(res);
})
.catch(error => {});
}
// 更新
function update(submitWay) {
console.log(appStore.openStyleStore[0], "123123123");
if (appStore.openStyleStore == void 0) {
Message.error("请装修楼层!");
return false;
}
progress.value = false;
let id = route.query.id;
const pagetype = route.query.pagetype;
console.log(appStore.openStyleStore, submitWay);
const pageType = {
INDEX: "INDEX",
ALERT: "OPEN_SCREEN_PAGE",
OPEN_SCREEN_ANIMATION: "OPEN_SCREEN_ANIMATION",
}[pagetype ? pagetype : "INDEX"];
if (pagetype) {
submitWay.pageData = JSON.stringify(
appStore.openStyleStore[0]
);
submitWay.pageType = pageType;
id = appStore.openStoreId;
}
API_Other.updateHome(id, submitWay)
.then((res) => {
num.value = 50;
if (res.success) {
num.value = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
saveDialog.value = false;
Message.success("修改成功");
goBack();
}, 1000);
} else {
saveDialog.value = false;
Message.error("修改失败,请稍后重试");
}
console.log(res);
})
.catch((error) => {});
}
// 返回查询数据页面
function goBack() {
router.go(-1);
}
// 保存
function submit(submitWay) {
progress.value = false;
API_Other.setHomeSetup(submitWay)
.then(res => {
num.value = 50;
if (res.success) {
num.value = 80;
/**制作保存成功动画¸ */
setTimeout(() => {
saveDialog.value = false;
Message.success("保存成功");
goBack();
}, 1000);
} else {
progress.value = true;
saveDialog.value = false;
Message.error("保存失败,请稍后重试");
}
console.log(res);
})
.catch(error => {});
}
</script>
<style scoped lang="scss">
.model-item {

View File

@@ -9,11 +9,9 @@
</el-carousel>
</div>
</template>
<script>
export default {
title: "导航栏",
props: ["res"],
};
<script setup>
defineOptions({ title: "导航栏" });
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -12,9 +12,12 @@
<script>
export default {
title: "五列单行图片模块",
props: ["res"],
};
</script>
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";
.layout {

View File

@@ -8,12 +8,12 @@
</div>
</template>
<script>
export default {
<script setup>
defineOptions({
title: "四列单行图片模块",
props: ["res"],
});
};
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -5,10 +5,8 @@
</div>
</div>
</template>
<script>
export default {
props: ['res']
}
<script setup>
defineProps(['res']);
</script>
<style lang="scss" scoped>
@import './tpl.scss';

View File

@@ -7,11 +7,12 @@
</div>
</template>
<script>
export default {
<script setup>
defineOptions({
title: "三列单行图片模块",
props: ["res"],
};
});
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -11,11 +11,14 @@
</div>
</template>
<script>
// 自定义选项(组件在 <component :is> 场景下按 title 展示名称),需保留在普通 script 块
export default {
title: "两张横图",
props: ["res"],
};
</script>
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";
.flex-two {

View File

@@ -39,59 +39,53 @@
</div>
</div>
</template>
<script>
<script setup>
import { computed, reactive, watch } from "vue";
import { CircleClose } from "@element-plus/icons-vue";
export default {
components: { CircleClose },
data() {
return {
selected: {
index: 0,
val: "",
},
};
const props = defineProps(["res"]);
const selected = reactive({
index: 0,
val: "",
});
const goodsBlock = computed(() => props.res?.list?.[0] || null);
watch(
goodsBlock,
(val) => {
if (!val) {
return;
}
const firstGoods = (val.listWay || []).find(Boolean);
if (firstGoods) {
selected.val = firstGoods.type;
} else if (val.titleWay?.[0]?.title) {
selected.val = val.titleWay[0].title;
}
},
props: ["res"],
computed: {
goodsBlock() {
return this.res?.list?.[0] || null;
},
},
watch: {
goodsBlock: {
handler(val) {
if (!val) {
return;
}
const firstGoods = (val.listWay || []).find(Boolean);
if (firstGoods) {
this.selected.val = firstGoods.type;
} else if (val.titleWay?.[0]?.title) {
this.selected.val = val.titleWay[0].title;
}
},
immediate: true,
},
},
methods: {
isGoodsVisible(item) {
if (!item) {
return false;
}
if (item.___index != undefined) {
return this.selected.index == item.___index;
}
return this.selected.val == item.type;
},
closeGoods(val, index) {
this.goodsBlock.listWay.splice(index, 1);
},
handleClickTitle(val, index) {
this.selected.index = index;
this.selected.val = val.title;
},
},
};
{ immediate: true }
);
function isGoodsVisible(item) {
if (!item) {
return false;
}
if (item.___index != undefined) {
return selected.index == item.___index;
}
return selected.val == item.type;
}
function closeGoods(val, index) {
goodsBlock.value.listWay.splice(index, 1);
}
function handleClickTitle(val, index) {
selected.index = index;
selected.val = val.title;
}
</script>
<style lang="scss" scoped>
.layout {

View File

@@ -27,10 +27,8 @@
</div>
</div>
</template>
<script>
export default {
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -27,10 +27,8 @@
</div>
</div>
</template>
<script>
export default {
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -27,10 +27,8 @@
</div>
</div>
</template>
<script>
export default {
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -15,11 +15,8 @@
</div>
</template>
<script>
export default {
title: "左一右二",
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -15,11 +15,8 @@
</div>
</template>
<script>
export default {
title: "左二右一",
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -10,10 +10,8 @@
</div>
</div>
</template>
<script>
export default {
props: ["res"],
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -5,12 +5,9 @@
</div>
</div>
</template>
<script>
<script setup>
import { Search } from "@element-plus/icons-vue";
export default {
components: { Search },
props: ['res']
}
defineProps(['res']);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -27,10 +27,8 @@
</div>
</div>
</template>
<script>
export default {
props: ["res"]
};
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -33,11 +33,14 @@
</template>
<script>
// 自定义选项(组件在 <component :is> 场景下按 title 展示名称),需保留在普通 script 块
export default {
title: "文字图片模板",
props: ["res"]
};
</script>
<script setup>
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";
.layout {

View File

@@ -25,11 +25,12 @@
</div>
</template>
<script>
export default {
<script setup>
defineOptions({
title: "标题栏",
props: ["res"],
};
});
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -15,11 +15,9 @@
</div>
</template>
<script>
export default {
title: "上一下二",
props: ["res"]
};
<script setup>
defineOptions({ title: "上一下二" });
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -14,11 +14,9 @@
</div>
</template>
<script>
export default {
title: "上二下一",
props: ["res"],
};
<script setup>
defineOptions({ title: "上二下一" });
defineProps(["res"]);
</script>
<style lang="scss" scoped>
@import "./tpl.scss";

View File

@@ -1,9 +1,7 @@
<template>
<div class="layout">请选择风格</div>
</template>
<script>
export default {
}
<script setup>
</script>
<style scoped lang="scss">
@import './tpl.scss';

View File

@@ -56,136 +56,143 @@
</el-card>
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router";
import { Message, Modal } from "@/utils/message";
import * as API_Other from "@/api/other.js";
export default {
data() {
return {
loading: false,
pageTypes: [
{ type: "INDEX", title: "首页" },
{ type: "SPECIAL", title: "专题" },
],
params: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
pageType: "INDEX",
pageClientType: "H5",
},
total: 0,
list: [],
};
},
mounted() {
this.init();
},
methods: {
handleTabChange(val) {
if (val == "ALERT") {
this.$router.push({
path: "/floorList/main",
query: { pagetype: val },
});
return;
}
if (val == "OPEN_SCREEN_ANIMATION") {
this.$router.push({
path: "/floorList/main",
query: { pagetype: val },
});
return;
}
this.params.pageNumber = 1;
this.params.pageType = val;
this.init();
},
changePageNum(val) {
this.params.pageNumber = val;
this.init();
},
beforeRelease(row) {
if (row.pageShow) {
this.$Message.warning(
this.total === 1
? "当前为唯一页面,无法关闭"
: "请直接开启其他页面,当前页面会自动关闭"
);
return false;
const router = useRouter();
const loading = ref(false);
const pageTypes = ref([
{ type: "INDEX", title: "首页" },
{ type: "SPECIAL", title: "专题" },
]);
const params = reactive({
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
pageType: "INDEX",
pageClientType: "H5",
});
const total = ref(0);
const list = ref([]);
onMounted(() => {
init();
});
function handleTabChange(val) {
if (val == "ALERT") {
router.push({
path: "/floorList/main",
query: { pagetype: val },
});
return;
}
if (val == "OPEN_SCREEN_ANIMATION") {
router.push({
path: "/floorList/main",
query: { pagetype: val },
});
return;
}
params.pageNumber = 1;
params.pageType = val;
init();
}
function changePageNum(val) {
params.pageNumber = val;
init();
}
function beforeRelease(row) {
if (row.pageShow) {
Message.warning(
total.value === 1
? "当前为唯一页面,无法关闭"
: "请直接开启其他页面,当前页面会自动关闭"
);
return false;
}
return new Promise((resolve, reject) => {
API_Other.releasePageHome(row.id).then((res) => {
if (res && res.success) {
Message.success("发布成功");
resolve(true);
init();
} else {
reject(new Error("release failed"));
}
return new Promise((resolve, reject) => {
API_Other.releasePageHome(row.id).then((res) => {
if (res && res.success) {
this.$Message.success("发布成功");
resolve(true);
this.init();
} else {
reject(new Error("release failed"));
}
}).catch(() => {
reject(new Error("release failed"));
});
});
}).catch(() => {
reject(new Error("release failed"));
});
});
}
function init() {
loading.value = true;
API_Other.getHomeList(params).then((res) => {
loading.value = false;
if (!res.result) return false;
res.result.records.forEach((item) => {
if (item.pageShow == "OPEN") {
item.pageShow = true;
} else {
item.pageShow = false;
}
});
list.value = res.result.records;
total.value = res.result.total;
});
}
function handleEdit(val) {
router.push({
path: "/floorList/main",
query: {
id: val.id,
name: val.name,
type: val.pageShow,
pagetype: params.pageType,
},
init() {
this.loading = true;
API_Other.getHomeList(this.params).then((res) => {
this.loading = false;
if (!res.result) return false;
res.result.records.forEach((item) => {
if (item.pageShow == "OPEN") {
item.pageShow = true;
} else {
item.pageShow = false;
}
});
this.list = res.result.records;
this.total = res.result.total;
});
},
handleEdit(val) {
this.$router.push({
path: "/floorList/main",
query: {
id: val.id,
name: val.name,
type: val.pageShow,
pagetype: this.params.pageType,
},
});
},
handleAdd() {
this.$router.push({
path: "/floorList/main",
query: { pagetype: this.params.pageType },
});
},
changePageSize(v) {
this.params.pageNumber = 1;
this.params.pageSize = v;
this.init();
},
confirmDel(row) {
this.$Modal.confirm({
title: "提示",
content: "删除此模板?",
onOk: () => this.handleDel(row),
});
},
handleDel(val) {
this.loading = true;
API_Other.removePageHome(val.id).then((res) => {
this.loading = false;
if (res.result) {
this.init();
this.$Message.success("删除成功");
}
});
},
},
};
});
}
function handleAdd() {
router.push({
path: "/floorList/main",
query: { pagetype: params.pageType },
});
}
function changePageSize(v) {
params.pageNumber = 1;
params.pageSize = v;
init();
}
function confirmDel(row) {
Modal.confirm({
title: "提示",
content: "删除此模板?",
onOk: () => handleDel(row),
});
}
function handleDel(val) {
loading.value = true;
API_Other.removePageHome(val.id).then((res) => {
loading.value = false;
if (res.result) {
init();
Message.success("删除成功");
}
});
}
</script>
<style scoped lang="scss">
.page-type-tabs {