forked from lxbfYeaaGbeDLMCi/deShanXiao
初始版本,目前线上可用
This commit is contained in:
10
frontEnd/src/pages/404/404.vue
Normal file
10
frontEnd/src/pages/404/404.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div>你寻找的页面失踪了</div>
|
||||
</template>
|
||||
|
||||
<script lang='ts' setup>
|
||||
import { reactive,onMounted} from 'vue'
|
||||
const data = reactive({})
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
</style>
|
||||
582
frontEnd/src/pages/checkout/checkout.vue
Normal file
582
frontEnd/src/pages/checkout/checkout.vue
Normal file
@@ -0,0 +1,582 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="结账登记"
|
||||
@resetSearch="methods.resetSearch"
|
||||
@search="methods.search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" :inline="true" label-position="right">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入逝者姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="searchForm.gender">
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="结账日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.purchaseDate"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择日期"
|
||||
end-placeholder="选择日期"
|
||||
@change="dataChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<template #toolsBar>
|
||||
<el-radio-group
|
||||
v-model="searchForm.retailState"
|
||||
size="small"
|
||||
style="margin-left: 15px">
|
||||
<el-radio-button label="未结账" :value="0" />
|
||||
<el-radio-button label="已结账" :value="1" />
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="80"
|
||||
fixed="left"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column
|
||||
prop="retailState"
|
||||
label="结账状态"
|
||||
width="160"
|
||||
fixed="left"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="
|
||||
row.retailState === 0
|
||||
? 'danger'
|
||||
: row.retailState === 1
|
||||
? 'success'
|
||||
: 'info'
|
||||
">
|
||||
{{
|
||||
row.retailState === 0
|
||||
? "未结账"
|
||||
: row.retailState === 1
|
||||
? "已结账"
|
||||
: "未知"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="逝者姓名"
|
||||
width="120"
|
||||
fixed="left"
|
||||
align="center" />
|
||||
<el-table-column prop="deceased.gender" label="性别" align="center" />
|
||||
<el-table-column prop="deceased.age" label="年龄" align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.idNumber"
|
||||
label="身份证"
|
||||
align="center"
|
||||
width="180" />
|
||||
<el-table-column
|
||||
prop="deceased.familyPhone"
|
||||
label="购买人电话"
|
||||
align="center"
|
||||
width="150" />
|
||||
<el-table-column
|
||||
prop="salesAmount"
|
||||
:label="'销售金额'"
|
||||
width="150"
|
||||
align="center" />
|
||||
|
||||
<el-table-column
|
||||
v-if="searchForm.retailState === 1"
|
||||
label="现金支付"
|
||||
width="150"
|
||||
prop="paymentRecord.cashAmount"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.paymentRecord?.cashAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="paymentRecord.unionPayAmount"
|
||||
label="银联支付"
|
||||
width="150"
|
||||
v-if="searchForm.retailState === 1"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.paymentRecord?.unionPayAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="paymentRecord.cardAmount"
|
||||
label="刷卡金额"
|
||||
width="150"
|
||||
v-if="searchForm.retailState === 1"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.paymentRecord?.cardAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="paymentRecord.publicTransferAmount"
|
||||
label="对公转账"
|
||||
width="150"
|
||||
v-if="searchForm.retailState === 1"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.paymentRecord?.publicTransferAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="paymentRecord.workshopPayment"
|
||||
label="车间支付"
|
||||
v-if="searchForm.retailState === 1"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.paymentRecord?.workshopPayment || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
:label="searchForm.retailState === 0 ? '录单时间' : '结账时间'"
|
||||
align="center"
|
||||
width="200">
|
||||
<template #default="{ row }">
|
||||
<span v-if="searchForm.retailState === 0">{{
|
||||
dayjs(row.createDate).format("YYYY-MM-DD HH:mm:ss")
|
||||
}}</span>
|
||||
<span v-if="searchForm.retailState === 1">
|
||||
{{
|
||||
dayjs(row.checkoutDate).format("YYYY-MM-DD HH:mm:ss")
|
||||
}}</span
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="购买人姓名"
|
||||
align="center"
|
||||
width="150" />
|
||||
|
||||
<el-table-column prop="remark" label="备注" align="center" />
|
||||
<el-table-column
|
||||
width="230"
|
||||
fixed="right"
|
||||
align="center"
|
||||
label="操作">
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; width: 100%; justify-content: center">
|
||||
<el-button
|
||||
v-if="row.retailState === 0"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.add(row)">
|
||||
结账登记
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.retailState === 1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.view(row)">
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.retailState === 1"
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.cancel(row)">
|
||||
作废
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="row.retailState === 1"
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.print(row)">
|
||||
打印
|
||||
<template #icon>
|
||||
<img
|
||||
src="/assets/icon/打印机.svg"
|
||||
style="margin-right: 5px"
|
||||
width="20"
|
||||
height="20" />
|
||||
</template>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="row.retailState === 0"
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.print(row)">
|
||||
打印
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="70%"
|
||||
:before-close="methods.handleDialogClose"
|
||||
@addConfim="methods.addConfim"
|
||||
@editConfim="methods.eidthConfirm"
|
||||
@closeConfirm="methods.handleDialogClose"
|
||||
confirmText="结账"
|
||||
destroy-on-close
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<checkoutAddOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
:deceased="currentRetail"
|
||||
v-model="currentPayment">
|
||||
</checkoutAddOrEdit>
|
||||
</template>
|
||||
<template #footer>
|
||||
<el-button @click="methods.print">打印</el-button>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
|
||||
<base-dialog
|
||||
v-model="cancelState.showDialog"
|
||||
title="账单作废"
|
||||
width="50%"
|
||||
destroy-on-close
|
||||
@closeConfirm="methods.cancleClose">
|
||||
<el-form :model="cancelForm" label-width="120px" style="padding: 20px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<!-- 注销申请人 -->
|
||||
<el-form-item label="作废申请人">
|
||||
<el-input disabled v-model="cancelForm.cancelPerson" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<!-- 注销日期 -->
|
||||
<el-form-item label="作废日期">
|
||||
<el-date-picker
|
||||
disabled
|
||||
v-model="cancelForm.cancelDate"
|
||||
type="date" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<!-- 注销原因 -->
|
||||
<el-form-item label="作废原因">
|
||||
<el-input
|
||||
v-model="cancelForm.cancelReason"
|
||||
type="textarea"
|
||||
placeholder="请输入作废原因" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="flex-center">
|
||||
<el-button type="primary" @click="methods.submitCancel"
|
||||
>作废</el-button
|
||||
>
|
||||
<el-button @click="methods.resetCancel">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</base-dialog>
|
||||
|
||||
<!-- <base-dialog v-model="showPrint" title="打印预览">
|
||||
<printRetailPage v-model="currentData"></printRetailPage>
|
||||
</base-dialog>
|
||||
|
||||
<base-dialog v-model="showPrint1" title="打印预览">
|
||||
<printServicesPage v-model="currentData"></printServicesPage>
|
||||
</base-dialog> -->
|
||||
<PrintRetailPage
|
||||
v-model="showPrint"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</PrintRetailPage>
|
||||
|
||||
<printServicesPage
|
||||
v-model="showPrint1"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</printServicesPage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch, nextTick } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import checkoutAddOrEdit from "./page/checkoutAddOrEdit.vue";
|
||||
import api from "@/lib/request";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import dayjs from "dayjs";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import PrintRetailPage from "@/components/printPage/printRetailPage.vue";
|
||||
import printServicesPage from "@/components/printPage/printServicesPage.vue";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "结账登记",
|
||||
edit: "登记修改",
|
||||
view: "查看登记",
|
||||
});
|
||||
|
||||
const globaUser = userInfor().userInfor;
|
||||
|
||||
const cancelState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
const cancelForm = ref({
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
name: "", // 逝者姓名
|
||||
gender: "", // 性别 (male / female / other)
|
||||
checkoutDate: "", // 结账日期 (YYYY-MM-DD)
|
||||
retailState: 0,
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
purchaseDate: ["", ""],
|
||||
});
|
||||
|
||||
let currentRetail = ref<RegisForm>(defaultRetail());
|
||||
|
||||
let showPrint = ref(false);
|
||||
let showPrint1 = ref(false);
|
||||
let deceased = ref();
|
||||
let serviceUrl = ref();
|
||||
|
||||
let table = ref();
|
||||
let currentData = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/checkout-retail/list?retailState=0",
|
||||
searchUrl: "/checkout-retail/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
let currentPayment = ref<PaymentForm>(defaultPaymentForm());
|
||||
|
||||
watch(
|
||||
() => searchForm.value.retailState,
|
||||
(newData) => {
|
||||
tableOption.value.url =
|
||||
"/checkout-retail/list?retailState=" + Number(newData);
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
);
|
||||
|
||||
const methods = {
|
||||
view(row: RegisForm) {
|
||||
currentRetail.value = row;
|
||||
currentData = row;
|
||||
currentPayment.value = row.paymentRecord || defaultPaymentForm();
|
||||
pageVisibleState.showPageType.view = true;
|
||||
pageVisibleState.showPageType.add = false;
|
||||
pageVisibleState.executeType.value = "view";
|
||||
},
|
||||
add(row: RegisForm) {
|
||||
currentData.value = row;
|
||||
currentRetail.value = row;
|
||||
currentPayment.value = row.paymentRecord || defaultPaymentForm();
|
||||
if (row.retailState === 1) {
|
||||
pageVisibleState.showPageType.view = true;
|
||||
} else {
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
pageVisibleState.executeType.value = "add";
|
||||
},
|
||||
|
||||
print(row: RegisForm) {
|
||||
deceased.value = row;
|
||||
serviceUrl.value =
|
||||
"/deceased-retail/selected-service?retailType=0&deceasedId=" +
|
||||
row.deceased.id;
|
||||
if (searchForm.value.retailState === 0) {
|
||||
showPrint1.value = true;
|
||||
} else {
|
||||
showPrint.value = true;
|
||||
}
|
||||
},
|
||||
|
||||
cancleClose() {
|
||||
currentRetail.value = defaultRetail();
|
||||
currentPayment.value = defaultPaymentForm();
|
||||
},
|
||||
|
||||
async addConfim() {
|
||||
await ElMessageBox.confirm("确定结账吗?", { type: "warning" });
|
||||
|
||||
let sendData = {
|
||||
deceasedRetail: {
|
||||
...currentRetail.value,
|
||||
},
|
||||
currentPayment: {
|
||||
...currentPayment.value,
|
||||
},
|
||||
id: currentData.value.id,
|
||||
};
|
||||
|
||||
const res = await api().post("/checkout-retail/confirmCheckout", sendData);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("结账成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
},
|
||||
eidthConfirm() {},
|
||||
search() {
|
||||
table.value.methods.setDataType("search");
|
||||
},
|
||||
resetSearch() {
|
||||
let retailState = searchForm.value.retailState;
|
||||
searchForm.value = {
|
||||
name: "", // 逝者姓名
|
||||
gender: "", // 性别 (male / female / other)
|
||||
checkoutDate: "", // 结账日期 (YYYY-MM-DD)
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
purchaseDate: ["", ""],
|
||||
retailState: retailState,
|
||||
};
|
||||
nextTick(() => {
|
||||
table.value.methods.setDataType("reset");
|
||||
});
|
||||
},
|
||||
handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
},
|
||||
|
||||
cancel(row: RegisForm) {
|
||||
currentRetail.value = row;
|
||||
cancelState.value.showDialog = true;
|
||||
},
|
||||
async submitCancel() {
|
||||
if (!cancelForm.value.cancelReason) {
|
||||
return ElMessage.error("请输入作废原因");
|
||||
}
|
||||
await ElMessageBox.confirm("确定作废吗?", { type: "warning" });
|
||||
|
||||
let sendData = {
|
||||
deceasedRetailId: currentRetail.value.id,
|
||||
cancelForm: { ...cancelForm.value },
|
||||
cancelType: 0,
|
||||
};
|
||||
|
||||
api()
|
||||
.post("/cancel/cancel", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("作废提交成功!");
|
||||
methods.resetCancel();
|
||||
cancelForm.value = {
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
};
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
resetCancel() {
|
||||
cancelForm.value = {
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
};
|
||||
cancelState.value.showDialog = false;
|
||||
},
|
||||
};
|
||||
function dataChange(val: Date[]) {
|
||||
searchForm.value.startDate = val[0];
|
||||
searchForm.value.endDate = val[1];
|
||||
}
|
||||
|
||||
const getSummaries = (param: { columns: any[]; data: any[] }) => {
|
||||
const { columns, data } = param;
|
||||
const sums: any[] = [];
|
||||
// 需要统计的字段列表
|
||||
const sumKeys = [
|
||||
"salesAmount",
|
||||
"paymentRecord.cashAmount",
|
||||
"paymentRecord.unionPayAmount",
|
||||
"paymentRecord.cardAmount",
|
||||
"paymentRecord.publicTransferAmount",
|
||||
"paymentRecord.workshopPayment",
|
||||
];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计";
|
||||
return;
|
||||
}
|
||||
if (sumKeys.includes(column.property)) {
|
||||
const values = data.map((item) => {
|
||||
const keys = column.property.split(".");
|
||||
let value = item;
|
||||
for (const key of keys) {
|
||||
value = value?.[key] || 0;
|
||||
}
|
||||
return Number(value) || 0;
|
||||
});
|
||||
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
const sum = values.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
sums[index] = `${sum.toFixed(2)}`;
|
||||
} else {
|
||||
sums[index] = "0.00 元";
|
||||
}
|
||||
} else {
|
||||
sums[index] = "";
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* 添加汇总行样式 */
|
||||
:deep(.el-table__footer) {
|
||||
.cell {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
303
frontEnd/src/pages/checkout/page/checkoutAddOrEdit.vue
Normal file
303
frontEnd/src/pages/checkout/page/checkoutAddOrEdit.vue
Normal file
@@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<div>
|
||||
<inforCard title="逝者信息">
|
||||
<el-form :model="checkoutForm" label-width="120px" disabled>
|
||||
<el-row :gutter="20" v-if="!deceased.deceased">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
:prefix-icon="User"
|
||||
v-model="deceased.name"
|
||||
disabled
|
||||
placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="deceased.gender" disabled>
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input v-model="deceased.idNumber" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄">
|
||||
<el-input v-model="deceased.age" disabled placeholder="年龄">
|
||||
</el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人" prop="buyer">
|
||||
<el-input v-model="deceased.familyName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人电话" prop="buyer">
|
||||
<el-input v-model="deceased.familyPhone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="deceased.purchaseDate"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="销售金额" prop="salesAmount">
|
||||
<el-input v-model.number="deceased.salesAmount" type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-else">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
:prefix-icon="User"
|
||||
v-model="deceased.deceased.name"
|
||||
disabled
|
||||
placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="deceased.deceased.gender" disabled>
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input v-model="deceased.deceased.idNumber" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄">
|
||||
<el-input v-model="deceased.deceased.age" disabled placeholder="年龄">
|
||||
</el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人" prop="buyer">
|
||||
<el-input v-model="deceased.deceased.familyName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人电话" prop="buyer">
|
||||
<el-input v-model="deceased.deceased.familyPhone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="deceased.deceased.purchaseDate"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="销售金额" prop="salesAmount">
|
||||
<el-input v-model.number="deceased.deceased.salesAmount" type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
<inforCard title="已选服务项目">
|
||||
<el-table
|
||||
:data="servicesList"
|
||||
style="max-height: 160px; overflow-y: auto">
|
||||
<el-table-column type="index" label="序号" width="80" />
|
||||
<el-table-column prop="name" label="项目名称" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="price" label="单价">
|
||||
<template #default="{ row }"> {{ row.price }} 元 </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总金额">
|
||||
<template #default="{ row }">
|
||||
{{ row.price * row.quantity }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</inforCard>
|
||||
<inforCard title="结账列表">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="checkoutForm"
|
||||
label-width="120px"
|
||||
label-position="right">
|
||||
<el-row :gutter="20">
|
||||
<!-- 第一行 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结账日期" prop="checkoutDate">
|
||||
<el-date-picker
|
||||
v-model="checkoutForm.checkoutDate"
|
||||
type="date"
|
||||
placeholder="结账日期"
|
||||
format="YYYY-MM-DD"
|
||||
disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="checkoutForm.settlementDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人" prop="handler">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="checkoutForm.handler"
|
||||
placeholder="经办人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="现金金额" prop="cash">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.cashAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('cashAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银联" prop="unionPay">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.unionPayAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('unionPayAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银行卡" prop="cardPay">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.cardAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('cardAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="对公" prop="transfer">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.publicTransferAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('publicTransferAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="车间支付" prop="transfer">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.workshopPayment"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('workshopPayment')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
// @ts-ignore
|
||||
import { User } from "@element-plus/icons-vue";
|
||||
import dayjs from "dayjs";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import request from "@/lib/request";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
executeType?: string;
|
||||
deceased: RegisForm;
|
||||
}>(),
|
||||
{
|
||||
deceased: () => defaultRetail(),
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(["updateData"]);
|
||||
const userInforStore = userInfor().userInfor;
|
||||
|
||||
let checkoutForm = defineModel({ default: defaultPaymentForm() });
|
||||
let servicesList = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
checkoutForm.value.handler =
|
||||
checkoutForm.value.handler || (userInforStore.name as string);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
let keys = [
|
||||
"cashAmount",
|
||||
"unionPayAmount",
|
||||
"cardAmount",
|
||||
"publicTransferAmount",
|
||||
"workshopPayment",
|
||||
];
|
||||
|
||||
function caleValue(keyVal: string) {
|
||||
let total = 0;
|
||||
let currentVal = checkoutForm.value[keyVal];
|
||||
|
||||
keys.forEach((key) => {
|
||||
if (keyVal !== key) {
|
||||
let tempVal = Number(checkoutForm.value[key]).toFixed(2);
|
||||
|
||||
total = Number(total) + Number(tempVal);
|
||||
}
|
||||
});
|
||||
let salesAmount = Number(props.deceased.salesAmount);
|
||||
|
||||
if (salesAmount - (total + currentVal) < 0) {
|
||||
checkoutForm.value[keyVal] = salesAmount - total;
|
||||
}
|
||||
}
|
||||
request()
|
||||
.get(
|
||||
"/deceased-retail/selected-service?deceasedId=" +
|
||||
props.deceased.deceased.id +
|
||||
"&retailType=0"
|
||||
)
|
||||
.then((res) => {
|
||||
servicesList.value = res.data?.list || [];
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
444
frontEnd/src/pages/funeralRetail/departedSaint/departedSaint.vue
Normal file
444
frontEnd/src/pages/funeralRetail/departedSaint/departedSaint.vue
Normal file
@@ -0,0 +1,444 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="逝者零售"
|
||||
@resetSearch="methods.resetSearch"
|
||||
@search="methods.search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" label-position="right">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.deceased.name"
|
||||
placeholder="请输入逝者姓名"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人姓名">
|
||||
<el-input
|
||||
v-model="searchForm.retail.familyName"
|
||||
placeholder="请输入购买人姓名"></el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="引导员">
|
||||
<GuideList v-model="searchForm.retail.guide"></GuideList>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="购买日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.retail.purchaseDate"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择日期"
|
||||
end-placeholder="选择日期"
|
||||
@change="dataChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<div style="margin-bottom: 15px">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.add"
|
||||
v-if="route.path === '/noDepartedSaint'">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<CirclePlus />
|
||||
</el-icon> </template
|
||||
>新增</el-button
|
||||
>
|
||||
</div>
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="80"
|
||||
fixed="left"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="结账"
|
||||
width="120"
|
||||
align="center"
|
||||
fixed="left">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.retailState === 1"
|
||||
>已结账</el-tag
|
||||
>
|
||||
<el-tag type="danger" v-if="row.retailState === 0">未结账</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="逝者姓名"
|
||||
fixed="left"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="familyName"
|
||||
label="购买人"
|
||||
align="center"
|
||||
fixed="left">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.deceased.familyName">
|
||||
{{ row.deceased.familyName }}
|
||||
</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="购买日期"
|
||||
width="200"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="结算日期"
|
||||
width="200"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retailState === 1"> {{ row.checkoutDate }} </span>
|
||||
<span v-else style="color: #999; font-style: italic">--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="salesAmount"
|
||||
label="销售金额"
|
||||
width="150"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
label="现金支付"
|
||||
width="150"
|
||||
prop="payment.cashAmount"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cashAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.unionPayAmount"
|
||||
label="银联支付"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.unionPayAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.cardAmount"
|
||||
label="刷卡金额"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cardAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.publicTransferAmount"
|
||||
label="对公转账"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.publicTransferAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.workshopPayment"
|
||||
label="车间支付"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.workshopPayment || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="handler" label="经办人" align="center" />
|
||||
|
||||
<el-table-column label="引导员" align="center">
|
||||
<template #default="{ row }">
|
||||
<span> {{ row.guide ?? row.deceased.guide }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
width="320"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-row align="middle" justify="center">
|
||||
<el-button
|
||||
v-if="row.retailState !== 1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.update(row)">
|
||||
修改</el-button
|
||||
>
|
||||
|
||||
<el-button @click="methods.viewProduct(row)" size="small">
|
||||
零售清单</el-button
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.print(row)"
|
||||
>打印</el-button
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
v-if="row.retailState !== 1"
|
||||
@click="methods.delete(row)">
|
||||
删除</el-button
|
||||
>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<retailList v-model="showDialog" :option="retailListTable"></retailList>
|
||||
|
||||
<baseDialog
|
||||
v-model="retailRegisState.showDialog"
|
||||
top="50px"
|
||||
:title="
|
||||
handlerType === 'add'
|
||||
? '新增登记'
|
||||
: handlerType === 'update'
|
||||
? '修改零售登记'
|
||||
: '零售登记'
|
||||
"
|
||||
@close="methods.dialogClose">
|
||||
<retailRegis
|
||||
:retailType="1"
|
||||
v-model="regisForm"
|
||||
type="零售修改"
|
||||
:showList="['逝者信息']"
|
||||
:add="handlerType === 'add'"></retailRegis>
|
||||
<template #footer>
|
||||
<el-row justify="center" align="middle" style="margin-top: 15px">
|
||||
<el-button type="primary" @click="methods.confirmUpdate"
|
||||
>保存</el-button
|
||||
>
|
||||
<el-button type="danger" @click="methods.close">关闭</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
</baseDialog>
|
||||
|
||||
<printServicesPage
|
||||
v-model="showPrint"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</printServicesPage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import { globalState } from "@/store";
|
||||
import retailRegis from "../publicComponents/retailRegis.vue";
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { useRoute } from "vue-router";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import PrintRetailPage from "@/components/printPage/printServicesPage.vue";
|
||||
import printServicesPage from "@/components/printPage/printServicesPage.vue";
|
||||
import GuideList from "@/components/guideList/guideList.vue";
|
||||
|
||||
const retailRegisState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
|
||||
let currentInfor = ref(undefined);
|
||||
let showDialog = ref(false);
|
||||
|
||||
let showPrint = ref(false);
|
||||
let deceased = ref();
|
||||
let serviceUrl = ref();
|
||||
|
||||
const handlerType = ref("");
|
||||
const searchForm = reactive({
|
||||
deceased: {
|
||||
name: "", // 逝者姓名
|
||||
},
|
||||
retail: {
|
||||
guide: "", // 引导员
|
||||
purchaseDate: "", // 购买日期
|
||||
retailType: 1,
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
familyName: "",
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const regisForm = ref<RegisForm>();
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/deceased-retail/list?retailType=1",
|
||||
searchUrl: "/deceased-retail/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
let retailListTable = ref<tableOptionType>({
|
||||
url: "/deceased-retail/selected-service",
|
||||
searchUrl: "",
|
||||
searchParams: {},
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
const methods = {
|
||||
update(row: RegisForm) {
|
||||
regisForm.value = row;
|
||||
handlerType.value = "update";
|
||||
retailRegisState.value.showDialog = true;
|
||||
},
|
||||
async confirmUpdate() {
|
||||
await ElMessageBox.confirm("确定保存修改吗?", { type: "warning" });
|
||||
let sendData = { ...regisForm.value };
|
||||
api()
|
||||
.post("/deceased-retail/update", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("修改成功");
|
||||
table.value.methods.setDataType("list");
|
||||
retailRegisState.value.showDialog = false;
|
||||
regisForm.value = defaultRetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
async delete(row: RegisForm) {
|
||||
await ElMessageBox.confirm("确定删除该条信息吗?", { type: "warning" });
|
||||
api()
|
||||
.get("/deceased-retail/delete", {
|
||||
params: {
|
||||
id: row.id,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("删除成功");
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
});
|
||||
},
|
||||
add() {
|
||||
retailRegisState.value.showDialog = true;
|
||||
handlerType.value = "add";
|
||||
},
|
||||
async viewProduct(row: RegisForm) {
|
||||
retailListTable.value.url =
|
||||
"/deceased-retail/selected-service?retailType=1&retailId=" +
|
||||
(row.retailId || row.id);
|
||||
showDialog.value = true;
|
||||
},
|
||||
drawerClose() {
|
||||
currentInfor.value = undefined;
|
||||
showDialog.value = false;
|
||||
},
|
||||
|
||||
close() {
|
||||
retailRegisState.value.showDialog = false;
|
||||
},
|
||||
async print(row: RegisForm) {
|
||||
deceased.value = row;
|
||||
showPrint.value = true;
|
||||
|
||||
serviceUrl.value =
|
||||
"/deceased-retail/selected-service?retailType=1&retailId=" +
|
||||
(row.retailId || row.id);
|
||||
},
|
||||
dialogClose() {
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
search() {
|
||||
searchForm.retail.retailType = 1;
|
||||
table.value.methods.setDataType("search");
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("reset");
|
||||
},
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
|
||||
const getSummaries = (param: { columns: any[]; data: any[] }) => {
|
||||
const { columns, data } = param;
|
||||
const sums: any[] = [];
|
||||
// 需要统计的字段列表
|
||||
const sumKeys = [
|
||||
"salesAmount",
|
||||
"payment.cashAmount",
|
||||
"payment.unionPayAmount",
|
||||
"payment.cardAmount",
|
||||
"payment.publicTransferAmount",
|
||||
"payment.workshopPayment",
|
||||
];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计";
|
||||
return;
|
||||
}
|
||||
if (sumKeys.includes(column.property)) {
|
||||
const values = data.map((item) => {
|
||||
const keys = column.property.split(".");
|
||||
let value = item;
|
||||
for (const key of keys) {
|
||||
value = value?.[key] || 0;
|
||||
}
|
||||
return Number(value) || 0;
|
||||
});
|
||||
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
const sum = values.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
sums[index] = `${sum.toFixed(2)}`;
|
||||
} else {
|
||||
sums[index] = "0.00 元";
|
||||
}
|
||||
} else {
|
||||
sums[index] = "";
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
};
|
||||
|
||||
function dataChange(val: Date[]) {
|
||||
searchForm.retail.startDate = val[0];
|
||||
searchForm.retail.endDate = val[1];
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* 添加汇总行样式 */
|
||||
:deep(.el-table__footer) {
|
||||
.cell {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
6
frontEnd/src/pages/funeralRetail/funeralRetail.vue
Normal file
6
frontEnd/src/pages/funeralRetail/funeralRetail.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,453 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="无逝者零售"
|
||||
@resetSearch="methods.resetSearch"
|
||||
@search="methods.search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" label-position="right">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.deceased.name"
|
||||
placeholder="请输入逝者姓名"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人姓名">
|
||||
<el-input
|
||||
v-model="searchForm.retail.familyName"
|
||||
placeholder="请输入购买人姓名"></el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="引导员">
|
||||
<GuideList v-model="searchForm.retail.guide"></GuideList>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<el-form-item label="购买日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.retail.purchaseDate"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择日期"
|
||||
end-placeholder="选择日期"
|
||||
@change="dataChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<template #toolsBar>
|
||||
<el-button size="small" type="primary" @click="methods.add">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<CirclePlus />
|
||||
</el-icon> </template
|
||||
>新增</el-button
|
||||
>
|
||||
</template>
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="80"
|
||||
fixed="left"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column label="结账" align="center" width="120" fixed="left">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" v-if="row.retailState === 1"
|
||||
>已结账</el-tag
|
||||
>
|
||||
<el-tag type="danger" v-if="row.retailState === 0">未结账</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="familyName"
|
||||
label="购买人"
|
||||
align="center"
|
||||
fixed="left">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.familyName">{{ row.familyName }}</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="deceasedName"
|
||||
label="逝者姓名"
|
||||
align="center"
|
||||
fixed="left">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.deceasedName">{{ row.deceasedName }}</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="购买日期"
|
||||
width="200"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="结算日期"
|
||||
width="200"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retailState === 1"> {{ row.checkoutDate }} </span>
|
||||
<span v-else style="color: #999; font-style: italic">--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="salesAmount" label="销售金额" align="center" />
|
||||
|
||||
<el-table-column
|
||||
label="现金支付"
|
||||
width="150"
|
||||
prop="payment.cashAmount"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cashAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.unionPayAmount"
|
||||
label="银联支付"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.unionPayAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.cardAmount"
|
||||
label="刷卡金额"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cardAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.publicTransferAmount"
|
||||
label="对公转账"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.publicTransferAmount || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.workshopPayment"
|
||||
label="车间支付"
|
||||
width="150"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.workshopPayment || "0.00" }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="handler" label="经办人" align="center" />
|
||||
<el-table-column prop="guide" label="引导员" align="center" />
|
||||
<el-table-column
|
||||
width="320"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-row align="middle" justify="center">
|
||||
<el-button
|
||||
v-if="row.retailState === 0"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.update(row)">
|
||||
修改</el-button
|
||||
>
|
||||
<el-button @click="methods.viewProduct(row)" size="small">
|
||||
零售清单</el-button
|
||||
>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.print(row)"
|
||||
>打印</el-button
|
||||
>
|
||||
<!-- <el-button
|
||||
type="primary"
|
||||
v-if="row.retailState === 0"
|
||||
@click="methods.checkout(row)"
|
||||
>结账</el-button
|
||||
> -->
|
||||
<el-button
|
||||
size="small"
|
||||
type="danger"
|
||||
v-if="row.retailState !== 1"
|
||||
@click="methods.delete(row)">
|
||||
删除</el-button
|
||||
>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<retailList v-model="showDialog" :option="retailListTable"></retailList>
|
||||
|
||||
<baseDialog
|
||||
v-model="retailRegisState.showDialog"
|
||||
top="30px"
|
||||
:title="
|
||||
handlerType === 'add'
|
||||
? '新增无逝者零售'
|
||||
: handlerType === 'update'
|
||||
? '修改无逝者登记'
|
||||
: '零售登记'
|
||||
"
|
||||
@close="methods.dialogClose">
|
||||
<retailRegis
|
||||
v-model="regisForm"
|
||||
:add="handlerType === 'add'"
|
||||
:retailType="2"
|
||||
:type="
|
||||
handlerType === 'add'
|
||||
? '新增无逝者零售'
|
||||
: handlerType === 'update'
|
||||
? '修改无逝者登记'
|
||||
: '零售登记'
|
||||
"></retailRegis>
|
||||
<template #footer>
|
||||
<el-row justify="center" align="middle" style="margin-top: 15px">
|
||||
<el-button type="primary" @click="methods.addConfirm">保存</el-button>
|
||||
<el-button type="danger" @click="methods.close">关闭</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
</baseDialog>
|
||||
|
||||
<printServicesPage
|
||||
v-model="showPrint"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</printServicesPage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import { globalState } from "@/store";
|
||||
import retailRegis from "../publicComponents/retailRegis.vue";
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import printServicesPage from "@/components/printPage/printServicesPage.vue";
|
||||
import GuideList from "@/components/guideList/guideList.vue";
|
||||
|
||||
let retailListTable = ref<tableOptionType>({
|
||||
url: "/deceased-retail/selected-service",
|
||||
searchUrl: "",
|
||||
searchParams: {},
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
let showPrint = ref(false);
|
||||
let deceased = ref();
|
||||
let serviceUrl = ref();
|
||||
|
||||
const retailRegisState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
|
||||
let currentInfor = ref(undefined);
|
||||
let showDialog = ref(false);
|
||||
|
||||
const handlerType = ref("新增无逝者零售");
|
||||
const searchForm = reactive({
|
||||
deceased: {
|
||||
name: "",
|
||||
},
|
||||
retail: {
|
||||
guide: "", // 引导员
|
||||
purchaseDate: "", // 购买日期
|
||||
retailType: 2,
|
||||
familyName: "",
|
||||
},
|
||||
});
|
||||
|
||||
const regisForm = ref<RegisForm>();
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/deceased-retail/list?retailType=2",
|
||||
searchUrl: "/deceased-retail/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
const methods = {
|
||||
update(row: RegisForm) {
|
||||
regisForm.value = row;
|
||||
handlerType.value = "update";
|
||||
retailRegisState.value.showDialog = true;
|
||||
},
|
||||
async delete(row: RegisForm) {
|
||||
await ElMessageBox.confirm("确定删除该条信息吗?", { type: "warning" });
|
||||
const res = await api().get("deceased-retail/delete", {
|
||||
params: {
|
||||
id: row.id,
|
||||
},
|
||||
});
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("删除成功");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res);
|
||||
}
|
||||
},
|
||||
add() {
|
||||
retailRegisState.value.showDialog = true;
|
||||
handlerType.value = "add";
|
||||
},
|
||||
viewProduct(row: RegisForm) {
|
||||
retailListTable.value.url =
|
||||
"/deceased-retail/selected-service?retailType=2&retailId=" + row.id;
|
||||
showDialog.value = true;
|
||||
},
|
||||
drawerClose() {
|
||||
currentInfor.value = undefined;
|
||||
showDialog.value = false;
|
||||
},
|
||||
async addConfirm() {
|
||||
let url = "/no-deceased-retail/add";
|
||||
if (handlerType.value === "update") url = "/no-deceased-retail/update";
|
||||
await ElMessageBox.confirm("确定保存吗?", {
|
||||
type: "warning",
|
||||
});
|
||||
let sendData = { ...regisForm.value };
|
||||
api()
|
||||
.post(url, sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("保存成功!");
|
||||
retailRegisState.value.showDialog = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
async checkout(row: RegisForm) {
|
||||
await ElMessageBox.confirm("确定结账吗?", { type: "warning" });
|
||||
|
||||
api()
|
||||
.get("/no-deceased-retail/checkout", {
|
||||
params: {
|
||||
id: Number(row.id),
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("结账成功!");
|
||||
retailRegisState.value.showDialog = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
retailRegisState.value.showDialog = false;
|
||||
},
|
||||
async print(row: any) {
|
||||
deceased.value = row;
|
||||
showPrint.value = true;
|
||||
|
||||
serviceUrl.value =
|
||||
"/deceased-retail/selected-service?retailType=2&retailId=" + row.id;
|
||||
},
|
||||
dialogClose() {
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
search() {
|
||||
searchForm.retail.retailType = 2;
|
||||
table.value.methods.setDataType("search");
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("reset");
|
||||
},
|
||||
};
|
||||
|
||||
const getSummaries = (param: { columns: any[]; data: any[] }) => {
|
||||
const { columns, data } = param;
|
||||
const sums: any[] = [];
|
||||
// 需要统计的字段列表
|
||||
const sumKeys = [
|
||||
"salesAmount",
|
||||
"payment.cashAmount",
|
||||
"payment.unionPayAmount",
|
||||
"payment.cardAmount",
|
||||
"payment.publicTransferAmount",
|
||||
"payment.workshopPayment",
|
||||
];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计";
|
||||
return;
|
||||
}
|
||||
if (sumKeys.includes(column.property)) {
|
||||
const values = data.map((item) => {
|
||||
const keys = column.property.split(".");
|
||||
let value = item;
|
||||
for (const key of keys) {
|
||||
value = value?.[key] || 0;
|
||||
}
|
||||
return Number(value) || 0;
|
||||
});
|
||||
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
const sum = values.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
sums[index] = `${sum.toFixed(2)}`;
|
||||
} else {
|
||||
sums[index] = "0.00 元";
|
||||
}
|
||||
} else {
|
||||
sums[index] = "";
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
};
|
||||
|
||||
function dataChange(val: Date[]) {
|
||||
searchForm.retail.startDate = val[0];
|
||||
searchForm.retail.endDate = val[1];
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* 添加汇总行样式 */
|
||||
:deep(.el-table__footer) {
|
||||
.cell {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,512 @@
|
||||
<template>
|
||||
<el-form
|
||||
style="max-height: 72vh; overflow-y: auto"
|
||||
ref="formRef"
|
||||
:model="regisForm"
|
||||
label-width="120px"
|
||||
label-position="right">
|
||||
<inforCard title="逝者信息" v-if="showList.includes('逝者信息')">
|
||||
<el-row :gutter="20" v-if="!regisForm.deceased">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="逝者姓名" prop="name">
|
||||
<el-input
|
||||
v-model="regisForm.name"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input
|
||||
v-model="regisForm.idNumber"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别" prop="gender">
|
||||
<el-radio-group
|
||||
v-model="regisForm.gender"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
">
|
||||
<el-radio-button label="男" value="男"></el-radio-button>
|
||||
<el-radio-button label="女" value="女"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄" prop="age">
|
||||
<el-input
|
||||
v-model="regisForm.age"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-else>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="逝者姓名" prop="name">
|
||||
<el-input
|
||||
v-model="regisForm.deceased.name"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input
|
||||
v-model="regisForm.deceased.idNumber"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别" prop="gender">
|
||||
<el-radio-group
|
||||
v-model="regisForm.deceased.gender"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
">
|
||||
<el-radio-button label="男" value="男"></el-radio-button>
|
||||
<el-radio-button label="女" value="女"></el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄" prop="age">
|
||||
<el-input
|
||||
v-model="regisForm.deceased.age"
|
||||
:disabled="
|
||||
props.type !== '服务修改' && props.type !== '服务登记'
|
||||
" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</inforCard>
|
||||
|
||||
<inforCard title="购买信息">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8" v-if="props.retailType === 2">
|
||||
<el-form-item label="逝者姓名" prop="deceasedName">
|
||||
<el-input
|
||||
v-model="regisForm.deceasedName"
|
||||
placeholder="请输入逝者姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form v-model="regisForm"></el-form>
|
||||
<el-form-item label="引导员" prop="guide">
|
||||
<GuideList v-model="regisForm.guide"></GuideList>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人" prop="buyer">
|
||||
<el-input
|
||||
:disabled="
|
||||
props.type !== '服务修改' &&
|
||||
props.type !== '服务登记' &&
|
||||
props.type !== '新增无逝者零售' &&
|
||||
props.type !== '修改无逝者登记'
|
||||
"
|
||||
v-model="regisForm.familyName"
|
||||
placeholder="请输入购买人姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人联系电话" prop="buyer">
|
||||
<el-input
|
||||
:disabled="
|
||||
props.type !== '服务修改' &&
|
||||
props.type !== '服务登记' &&
|
||||
props.type !== '新增无逝者零售' &&
|
||||
props.type !== '修改无逝者登记'
|
||||
"
|
||||
v-model="regisForm.familyPhone"
|
||||
placeholder="请输入购买人电话" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="所在区域">
|
||||
<el-cascader
|
||||
:disabled="
|
||||
props.type !== '服务修改' &&
|
||||
props.type !== '服务登记' &&
|
||||
props.type !== '新增无逝者零售' &&
|
||||
props.type !== '修改无逝者登记'
|
||||
"
|
||||
:options="pcaTextArrData"
|
||||
v-model="selectedOptions"
|
||||
@change="methods.pcaChange"></el-cascader> </el-form-item
|
||||
></el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="详细地址">
|
||||
<el-input
|
||||
v-model="regisForm.address"
|
||||
:disabled="
|
||||
props.type !== '服务修改' &&
|
||||
props.type !== '服务登记' &&
|
||||
props.type !== '新增无逝者零售' &&
|
||||
props.type !== '修改无逝者登记'
|
||||
"
|
||||
placeholder="请输入你的地址"></el-input> </el-form-item
|
||||
></el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="regisForm.purchaseDate"
|
||||
type="datetime"
|
||||
placeholder="选择日期"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人" prop="handler">
|
||||
<el-input
|
||||
v-model="regisForm.handler"
|
||||
disabled
|
||||
placeholder="请输入经办人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="销售金额" prop="salesAmount">
|
||||
<el-input
|
||||
v-model.number="regisForm.salesAmount"
|
||||
disabled
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</inforCard>
|
||||
|
||||
<inforCard title="已选服务项目">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="methods.addServiceItem"
|
||||
v-if="props.type !== '零售结算'"
|
||||
>新增项目</el-button
|
||||
>
|
||||
<el-button
|
||||
type="default"
|
||||
size="small"
|
||||
@click="methods.customInput"
|
||||
v-if="props.type !== '零售结算'"
|
||||
>手工录入</el-button
|
||||
>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="regisForm.services"
|
||||
:style="{ marginTop: (props.type !== '零售结算' ? 15 : 0) + 'px' }">
|
||||
<el-table-column type="index" label="序号" width="80" />
|
||||
<el-table-column prop="name" label="项目名称" />
|
||||
<el-table-column prop="quantity" label="数量" width="80">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.name === '殡仪定制服务'">
|
||||
<el-input v-model="row.quantity"></el-input>
|
||||
</span>
|
||||
<span v-else>{{ row.quantity }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="单位" width="80">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.name === '殡仪定制服务'">
|
||||
<el-input v-model="row.unit"></el-input>
|
||||
</span>
|
||||
<span v-else>{{ row.unit }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="单价(元)">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.name === '殡仪定制服务'">
|
||||
<el-input v-model="row.price"></el-input>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ row.price }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总金额">
|
||||
<template #default="{ row }">
|
||||
{{ row.price * row.quantity }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" width="200" label="备注">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
:content="row.remark"
|
||||
placement="top">
|
||||
<p
|
||||
style="
|
||||
white-space: nowrap; /* 强制不换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
">
|
||||
{{ row.remark }}
|
||||
</p>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column>
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
v-if="props.showServiceDelBtn"
|
||||
@click="methods.removeProduct(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</inforCard>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="customServiceState.show2LevelPage.value"
|
||||
title="手工录入服务"
|
||||
width="50%"
|
||||
@addConfim="addConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="customServiceState.showPageType">
|
||||
<template #content>
|
||||
<serviceListaddOrEdit
|
||||
type="手工录入服务"
|
||||
:executeType="customServiceState.executeType.value"
|
||||
v-model="currentServiceItem"></serviceListaddOrEdit>
|
||||
</template>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="methods.confirmCustomService"
|
||||
>确定</el-button
|
||||
>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
<el-drawer
|
||||
v-model="serviceItemState.showDrawer"
|
||||
size="50%"
|
||||
:with-header="false">
|
||||
<serviceItemSelect v-model="regisForm.services"></serviceItemSelect>
|
||||
</el-drawer>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, ref, watch } from "vue";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import serviceItemSelect from "./serviceItemSelect.vue";
|
||||
import dayjs from "dayjs";
|
||||
import api from "@/lib/request";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import serviceListaddOrEdit from "../../serviceList/serviceItem/page/addOrEdit.vue";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import { defaultServiceItem } from "@/defaultForm/defaultSerivceItem";
|
||||
import { pcaTextArr } from "element-china-area-data";
|
||||
import GuideList from "@/components/guideList/guideList.vue";
|
||||
|
||||
const formRef = ref();
|
||||
const userStoreState = userInfor();
|
||||
const serviceItemState = ref({
|
||||
showDrawer: false,
|
||||
});
|
||||
|
||||
const customServiceState = new pageVisible({
|
||||
add: "新增服务项目",
|
||||
edit: "服务项目编辑",
|
||||
view: "服务项目查看",
|
||||
});
|
||||
|
||||
// 表单数据
|
||||
const regisForm = defineModel<RegisForm>({
|
||||
default: defaultRetail(),
|
||||
});
|
||||
|
||||
const selectedOptions = ref([
|
||||
regisForm.value.province,
|
||||
regisForm.value.city,
|
||||
regisForm.value.area,
|
||||
]);
|
||||
|
||||
const pcaTextArrData = ref(pcaTextArr);
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
add?: boolean;
|
||||
type?: RegistrationType;
|
||||
showServiceDelBtn?: boolean;
|
||||
retailType?: number;
|
||||
showList?: string[];
|
||||
}>(),
|
||||
{
|
||||
add: false,
|
||||
showServiceDelBtn: true,
|
||||
type: "服务登记",
|
||||
retailType: 0,
|
||||
showList: () => [],
|
||||
}
|
||||
);
|
||||
|
||||
if (["零售登记", "服务登记"].includes(props.type)) {
|
||||
regisForm.value.serviceItems = "";
|
||||
regisForm.value.services = [];
|
||||
}
|
||||
|
||||
const methods = {
|
||||
addServiceItem() {
|
||||
if (!regisForm.value.services?.length) {
|
||||
regisForm.value.services = [];
|
||||
}
|
||||
serviceItemState.value.showDrawer = true;
|
||||
},
|
||||
removeProduct(row: Product) {
|
||||
let index = regisForm.value.services?.findIndex(
|
||||
(item: any) => item.name === row.name
|
||||
);
|
||||
regisForm.value.services = regisForm.value.services?.filter(
|
||||
(_, i) => i !== index
|
||||
);
|
||||
},
|
||||
customInput() {
|
||||
customServiceState.show2LevelPage.value = true;
|
||||
},
|
||||
async confirmCustomService() {
|
||||
if (!currentServiceItem.value.name)
|
||||
return ElMessage.warning("服务项目名称不能为空!");
|
||||
if (
|
||||
currentServiceItem.value.price <= 0 ||
|
||||
currentServiceItem.value.quantity <= 0
|
||||
) {
|
||||
await ElMessageBox.confirm(
|
||||
"该商品售价或商品数量为0,是否继续?",
|
||||
"提示",
|
||||
{
|
||||
type: "warning",
|
||||
}
|
||||
);
|
||||
if (!regisForm.value.services) regisForm.value.services = [];
|
||||
regisForm.value.services.push({ ...currentServiceItem.value });
|
||||
customServiceState.show2LevelPage.value = false;
|
||||
|
||||
currentServiceItem.value = defaultServiceItem();
|
||||
return;
|
||||
}
|
||||
await ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!regisForm.value.services) regisForm.value.services = [];
|
||||
regisForm.value.services.push({ ...currentServiceItem.value });
|
||||
customServiceState.show2LevelPage.value = false;
|
||||
|
||||
currentServiceItem.value = defaultServiceItem();
|
||||
},
|
||||
pcaChange(data: { [key: string]: any }) {
|
||||
regisForm.value.province = data[0];
|
||||
regisForm.value.city = data[1];
|
||||
regisForm.value.area = data[2];
|
||||
},
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
if (
|
||||
!["零售登记", "服务登记"].includes(props.type) &&
|
||||
(regisForm.value.deceasedId || regisForm.value.id)
|
||||
) {
|
||||
let url =
|
||||
"/deceased-retail/selected-service?deceasedId=" +
|
||||
(regisForm.value.deceasedId || regisForm.value.id) +
|
||||
"&retailType=" +
|
||||
props.retailType;
|
||||
|
||||
if (regisForm.value.id && props.retailType === 2) {
|
||||
url =
|
||||
"/deceased-retail/selected-service?retailId=" +
|
||||
regisForm.value.id +
|
||||
"&retailType=" +
|
||||
props.retailType;
|
||||
}
|
||||
|
||||
if (["零售修改", "零售结算"].includes(props.type)) {
|
||||
url =
|
||||
"/deceased-retail/selected-service?retailId=" +
|
||||
regisForm.value.id +
|
||||
"&retailType=" +
|
||||
props.retailType;
|
||||
}
|
||||
|
||||
const selectedService = await api().get(url);
|
||||
|
||||
regisForm.value.services = selectedService.data.list;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => regisForm.value.services,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
regisForm.value.salesAmount = 0;
|
||||
newVal?.forEach(
|
||||
(item) => (regisForm.value.salesAmount += item.price * item.quantity)
|
||||
);
|
||||
|
||||
if (props.type === "服务登记") {
|
||||
regisForm.value.serviceItems = newVal
|
||||
.map((item) => item.id)
|
||||
.join(",");
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
regisForm.value = {
|
||||
...regisForm.value,
|
||||
handler: regisForm.value.handler || userStoreState.userInfor.name || "",
|
||||
purchaseDate:
|
||||
regisForm.value.purchaseDate ||
|
||||
dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
|
||||
};
|
||||
});
|
||||
let currentServiceItem = ref<ServiceItemType>(defaultServiceItem());
|
||||
async function addConfim() {
|
||||
await ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
if (!regisForm.value.services) regisForm.value.services = [];
|
||||
regisForm.value.services.push({ ...currentServiceItem.value });
|
||||
|
||||
// await ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
// type: "warning",
|
||||
// });
|
||||
// let res = await api().post("/service-item/add", currentServiceItem.value);
|
||||
// if (res.code === 200) {
|
||||
// ElMessage.success("添加成功");
|
||||
// customServiceState.show2LevelPage.value = false;
|
||||
// } else {
|
||||
// ElMessage.error(res.msg);
|
||||
// }
|
||||
}
|
||||
|
||||
function handleDialogClose() {
|
||||
customServiceState.show2LevelPage.value = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,353 @@
|
||||
<template>
|
||||
<div class="service-selection">
|
||||
<!-- 标题 -->
|
||||
<h2 class="title">服务项目选择</h2>
|
||||
<!-- 搜索框 -->
|
||||
|
||||
<el-form>
|
||||
<el-row :gutter="15" style="margin-top: 15px">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="商品名称">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
placeholder="请输入商品名称"
|
||||
clearable />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-form-item label="价格">
|
||||
<el-input-number
|
||||
v-model="price"
|
||||
:min="0"
|
||||
clearable
|
||||
placeholder="请输入价格"
|
||||
type="number"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-divider style="margin: 8px 0; margin-bottom: 30px" />
|
||||
<!-- 两列布局 -->
|
||||
<div
|
||||
class="content"
|
||||
v-loading="lodaing"
|
||||
element-loading-text="数据加载中....">
|
||||
<!-- 左侧树结构 -->
|
||||
<div class="left">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="categoryTree"
|
||||
:props="treeProps"
|
||||
show-checkbox
|
||||
check-strictly
|
||||
@check="getCheckedKeys" />
|
||||
</div>
|
||||
|
||||
<!-- 右侧商品列表 -->
|
||||
<div class="right">
|
||||
<div
|
||||
v-for="(item, index) in categoryServiceList"
|
||||
:key="index"
|
||||
class="item">
|
||||
<!-- 商品信息 -->
|
||||
<div class="item-info">
|
||||
<div class="item-name">商品名称:{{ item.name }}</div>
|
||||
<div class="item-group">
|
||||
所属分类:{{
|
||||
categoryTreeAll.find((fitem) => fitem.id === item.parentId)
|
||||
?.name || "无"
|
||||
}}
|
||||
</div>
|
||||
<div class="item-price">
|
||||
{{ item.price }} 元 / {{ item.unit || "(暂无单位)" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加/删除按钮 -->
|
||||
<div class="item-actions">
|
||||
<!-- <el-button
|
||||
v-if="!item.quantity || item.quantity === 0"
|
||||
type="primary"
|
||||
@click="addItem(item)">
|
||||
<span style="color: #fff">+ 添加</span>
|
||||
</el-button>
|
||||
<div v-else class="quantity-control">
|
||||
<el-button type="danger" @click="removeItem(item)">-</el-button>
|
||||
<span class="quantity">{{ item.quantity }}</span>
|
||||
<el-button type="primary" @click="addItem(item)">+ </el-button>
|
||||
</div> -->
|
||||
|
||||
<el-input-number
|
||||
style="margin-top: 5px"
|
||||
v-model="item.quantity"
|
||||
:min="0"
|
||||
@change="methods.quantityChange(item)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部悬浮框 -->
|
||||
<div class="footer">
|
||||
<div class="footer-item">
|
||||
<span>总金额:</span>
|
||||
<span
|
||||
><span class="red-font">{{ totalAmount }} </span>元</span
|
||||
>
|
||||
</div>
|
||||
<!-- <div class="footer-item">
|
||||
<span>减免金额:</span>
|
||||
<span
|
||||
><span class="green-font">
|
||||
{{ discountAmount }}
|
||||
</span>
|
||||
元</span
|
||||
>
|
||||
</div>
|
||||
<div class="footer-item">
|
||||
<span>实收金额:</span>
|
||||
<span
|
||||
><span class="red-font">
|
||||
{{ actualAmount }}
|
||||
</span>
|
||||
元</span
|
||||
>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from "vue";
|
||||
import api from "@/lib/request";
|
||||
|
||||
const emits = defineEmits(["selectedProduct"]);
|
||||
const products = defineModel<Product[]>();
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref("");
|
||||
const price = ref(0);
|
||||
|
||||
const lodaing = ref(false);
|
||||
|
||||
// 分类树数据
|
||||
const categoryTree = ref([]);
|
||||
const categoryTreeAll = ref([]);
|
||||
const categoryServiceAll = ref<Product[]>([]);
|
||||
const selectedCategory = ref([]);
|
||||
const tree = ref();
|
||||
|
||||
const categoryServiceList = computed(() => {
|
||||
let resData: Product[] = [];
|
||||
selectedCategory.value.forEach((item) => {
|
||||
let findData = categoryServiceAll.value.filter(
|
||||
(fitem) => fitem.parentId === item.id
|
||||
);
|
||||
if (findData) {
|
||||
resData = [...resData, ...findData];
|
||||
}
|
||||
});
|
||||
let res = selectedCategory.value.length ? resData : categoryServiceAll.value;
|
||||
|
||||
if (searchKeyword.value) {
|
||||
res = res.filter((item) => item.name.includes(searchKeyword.value));
|
||||
let includeCategory = categoryTreeAll.value.filter((category) =>
|
||||
category.name.includes(searchKeyword.value)
|
||||
);
|
||||
categoryServiceAll.value.forEach((item) => {
|
||||
includeCategory.forEach((iitem) => {
|
||||
if (
|
||||
item.parentId === iitem.id &&
|
||||
!res.find((fitem) => fitem.name === item.name)
|
||||
) {
|
||||
res.unshift(item);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (price.value && price.value !== 0) {
|
||||
res = res.filter((fitem) => Number(fitem.price) === price.value);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
// 树结构配置
|
||||
const treeProps = {
|
||||
children: "children",
|
||||
label: "name",
|
||||
};
|
||||
|
||||
const syncProductsWithCategoryServiceAll = () => {
|
||||
if (!products.value) return; // 防止 products 为空时报错
|
||||
|
||||
categoryServiceAll.value.forEach((item) => {
|
||||
const findItem = products.value?.find(
|
||||
(newItem) => newItem.name === item.name
|
||||
);
|
||||
if (findItem) {
|
||||
item.quantity = findItem.quantity;
|
||||
} else {
|
||||
item.quantity = 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => products.value,
|
||||
(newVal) => {
|
||||
syncProductsWithCategoryServiceAll();
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
// 总金额
|
||||
const totalAmount = computed(() => {
|
||||
return categoryServiceAll.value.reduce(
|
||||
(sum, item) => sum + item.price * (item.quantity || 0),
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
const methods = {
|
||||
quantityChange(item: any) {
|
||||
let findData = products.value?.find(
|
||||
(findItem) => findItem.name === item.name
|
||||
);
|
||||
if (!findData) {
|
||||
products.value?.push(item);
|
||||
} else {
|
||||
findData.quantity = item.quantity;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const getCheckedKeys = (data: any) => {
|
||||
selectedCategory.value = tree.value.getCheckedNodes();
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
lodaing.value = true;
|
||||
let treeList = await api().get("/service-category/list");
|
||||
let allTreeList = await api().get("/service-category/list", {
|
||||
params: { all: true },
|
||||
});
|
||||
let allService = await api().get("/service-item/list", {
|
||||
params: { all: true },
|
||||
});
|
||||
|
||||
categoryTree.value = treeList.data.list;
|
||||
categoryServiceAll.value = allService.data.list;
|
||||
categoryTreeAll.value = allTreeList.data.list;
|
||||
|
||||
syncProductsWithCategoryServiceAll();
|
||||
|
||||
lodaing.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.service-selection {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.search-box {
|
||||
margin-bottom: 20px;
|
||||
width: 50%;
|
||||
}
|
||||
.left {
|
||||
width: 200px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 30px;
|
||||
max-height: calc(100vh - 150px);
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: calc(50% - 10px);
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
flex-direction: column;
|
||||
// .item-image {
|
||||
// width: 100px;
|
||||
// height: 100px;
|
||||
// margin-right: 10px;
|
||||
// }
|
||||
.item-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.item-category,
|
||||
.item-group,
|
||||
.item-price {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
.item-actions {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.quantity-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.quantity {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
z-index: 10;
|
||||
background: #fff;
|
||||
padding: 10px 20px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
|
||||
.footer-item {
|
||||
font-size: 14px;
|
||||
}
|
||||
.red-font,
|
||||
.green-font {
|
||||
font-size: 18px;
|
||||
color: #f04b22;
|
||||
font-weight: bold;
|
||||
padding-right: 8px;
|
||||
}
|
||||
.green-font {
|
||||
color: #67c23a;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<div>
|
||||
<inforCard title="逝者信息">
|
||||
<el-form :model="checkoutForm" label-width="120px" disabled>
|
||||
<el-row :gutter="20" v-if="deceased.deceased">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
:prefix-icon="User"
|
||||
v-model="deceased.deceased.name"
|
||||
disabled
|
||||
placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="deceased.deceased.gender" disabled>
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input v-model="deceased.deceased.idNumber" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄">
|
||||
<el-input
|
||||
v-model="deceased.deceased.age"
|
||||
disabled
|
||||
placeholder="年龄">
|
||||
</el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人名" prop="buyer">
|
||||
<el-input v-model="deceased.deceased.familyName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人电话" prop="buyer">
|
||||
<el-input v-model="deceased.deceased.familyPhone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="deceased.purchaseDate"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="销售金额" prop="salesAmount">
|
||||
<el-input v-model.number="deceased.salesAmount" type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20" v-else>
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
:prefix-icon="User"
|
||||
v-model="deceased.name"
|
||||
disabled
|
||||
placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="deceased.gender" disabled>
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input v-model="deceased.idNumber" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄">
|
||||
<el-input v-model="deceased.age" disabled placeholder="年龄">
|
||||
</el-input> </el-form-item
|
||||
></el-col> -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人姓名" prop="buyer">
|
||||
<el-input v-model="deceased.familyName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人电话" prop="buyer">
|
||||
<el-input v-model="deceased.familyPhone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="deceased.purchaseDate"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="销售金额" prop="salesAmount">
|
||||
<el-input v-model.number="deceased.salesAmount" type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
<inforCard title="已选服务项目">
|
||||
<el-table
|
||||
:data="servicesList"
|
||||
style="max-height: 160px; overflow-y: auto">
|
||||
<el-table-column type="index" label="序号" width="80" />
|
||||
<el-table-column prop="name" label="项目名称" />
|
||||
<el-table-column prop="quantity" label="数量" />
|
||||
<el-table-column prop="unit" label="单位" />
|
||||
<el-table-column prop="price" label="单价">
|
||||
<template #default="{ row }"> {{ row.price }} 元 </template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="总金额">
|
||||
<template #default="{ row }">
|
||||
{{ row.price * row.quantity }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</inforCard>
|
||||
<inforCard title="结账列表">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="checkoutForm"
|
||||
label-width="120px"
|
||||
label-position="right">
|
||||
<el-row :gutter="20">
|
||||
<!-- 第一行 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结账日期" prop="checkoutDate">
|
||||
<el-date-picker
|
||||
v-model="checkoutForm.checkoutDate"
|
||||
type="date"
|
||||
placeholder="结账日期"
|
||||
format="YYYY-MM-DD"
|
||||
disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="checkoutForm.settlementDate"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人" prop="handler">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="checkoutForm.handler"
|
||||
placeholder="经办人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="现金金额" prop="cash">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.cashAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('cashAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银联" prop="unionPay">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.unionPayAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('unionPayAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银行卡" prop="cardPay">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.cardAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('cardAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="对公" prop="transfer">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.publicTransferAmount"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('publicTransferAmount')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="车间支付" prop="transfer">
|
||||
<el-input
|
||||
v-model.number="checkoutForm.workshopPayment"
|
||||
type="number"
|
||||
:min="0"
|
||||
@input="caleValue('workshopPayment')">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
// @ts-ignore
|
||||
import { User } from "@element-plus/icons-vue";
|
||||
import dayjs from "dayjs";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import request from "@/lib/request";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
executeType?: string;
|
||||
deceased: RegisForm;
|
||||
}>(),
|
||||
{
|
||||
deceased: () => {
|
||||
return {
|
||||
...defaultRetail(),
|
||||
deceased: {},
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits(["updateData"]);
|
||||
const userInforStore = userInfor().userInfor;
|
||||
|
||||
let checkoutForm = defineModel({ default: defaultPaymentForm() });
|
||||
let servicesList = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
checkoutForm.value.handler =
|
||||
checkoutForm.value.handler || (userInforStore.name as string);
|
||||
request()
|
||||
.get(
|
||||
"/deceased-retail/selected-service?retailId=" +
|
||||
props.deceased.id +
|
||||
"&retailType=" +
|
||||
props.deceased.retailType
|
||||
)
|
||||
.then((res) => {
|
||||
servicesList.value = res.data?.list || [];
|
||||
});
|
||||
});
|
||||
|
||||
let keys = [
|
||||
"cashAmount",
|
||||
"unionPayAmount",
|
||||
"cardAmount",
|
||||
"publicTransferAmount",
|
||||
"workshopPayment",
|
||||
];
|
||||
|
||||
function caleValue(keyVal: string) {
|
||||
let total = 0;
|
||||
let currentVal = checkoutForm.value[keyVal];
|
||||
|
||||
keys.forEach((key) => {
|
||||
if (keyVal !== key) {
|
||||
let tempVal = Number(checkoutForm.value[key]).toFixed(2);
|
||||
total = Number(total) + Number(tempVal);
|
||||
}
|
||||
});
|
||||
let salesAmount = Number(props.deceased.salesAmount);
|
||||
|
||||
if (salesAmount - (total + currentVal) < 0) {
|
||||
checkoutForm.value[keyVal] = salesAmount - total;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
643
frontEnd/src/pages/funeralRetail/saintCheckout/saintCheckout.vue
Normal file
643
frontEnd/src/pages/funeralRetail/saintCheckout/saintCheckout.vue
Normal file
@@ -0,0 +1,643 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="零售结算"
|
||||
@resetSearch="methods.resetSearch"
|
||||
@search="methods.search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" label-position="right">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.deceased.name"
|
||||
placeholder="请输入逝者姓名"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人姓名">
|
||||
<el-input
|
||||
v-model="searchForm.retail.familyName"
|
||||
placeholder="请输入购买人姓名"></el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="引导员">
|
||||
<GuideList
|
||||
v-model="
|
||||
searchForm.retail.guide
|
||||
"></GuideList> </el-form-item
|
||||
></el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.retail.purchaseDate"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择日期"
|
||||
end-placeholder="选择日期"
|
||||
@change="dataChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<div style="margin-bottom: 15px">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.add"
|
||||
v-if="route.path === '/noDepartedSaint'">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<CirclePlus />
|
||||
</el-icon> </template
|
||||
>新增</el-button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<template #toolsBar>
|
||||
<el-radio-group
|
||||
v-model="searchForm.retail.retailType"
|
||||
size="small"
|
||||
style="margin-left: 15px">
|
||||
<el-radio-button label="逝者零售" :value="1" />
|
||||
<el-radio-button label="无逝者零售" :value="2" />
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="80"
|
||||
fixed="left"
|
||||
align="center"></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="逝者姓名"
|
||||
width="100"
|
||||
fixed="left"
|
||||
v-if="searchForm.retail.retailType === 1"
|
||||
align="center">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="结账"
|
||||
width="100"
|
||||
fixed="left"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="
|
||||
row.retailState === 0
|
||||
? 'danger'
|
||||
: row.retailState === 1
|
||||
? 'success'
|
||||
: 'info'
|
||||
">
|
||||
{{
|
||||
row.retailState === 0
|
||||
? "未结账"
|
||||
: row.retailState === 1
|
||||
? "已结账"
|
||||
: "未知"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="购买人" align="center" fixed="left">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.familyName || row.deceased?.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="familyPhone"
|
||||
label="购买人电话"
|
||||
width="120"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.deceased?.familyPhone || row.familyPhone }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="purchaseDate"
|
||||
label="购买日期"
|
||||
width="200"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="checkoutDate"
|
||||
label="结算日期"
|
||||
width="200"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retailState === 1">
|
||||
{{ row.checkoutDate }}
|
||||
</span>
|
||||
<span v-else>--</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="handler" label="经办人" align="center" />
|
||||
<el-table-column
|
||||
width="100"
|
||||
prop="salesAmount"
|
||||
label="销售金额"
|
||||
align="center" />
|
||||
|
||||
<el-table-column
|
||||
label="现金支付"
|
||||
prop="payment.cashAmount"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cashAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.unionPayAmount"
|
||||
label="银联支付"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.unionPayAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.cardAmount"
|
||||
label="刷卡金额"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cardAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.publicTransferAmount"
|
||||
label="对公转账"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.publicTransferAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.workshopPayment"
|
||||
label="车间支付"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.workshopPayment || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="guide" label="引导员" align="center" />
|
||||
<el-table-column
|
||||
width="300"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-row align="middle" justify="center">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
v-if="row.retailState === 1"
|
||||
@click="methods.hanlderView(row)">
|
||||
查看</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="methods.checkout(row)"
|
||||
v-if="row.retailState === 0"
|
||||
>结账</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="row.retailState === 1"
|
||||
size="small"
|
||||
type="default"
|
||||
@click="methods.cancel(row)">
|
||||
作废
|
||||
</el-button>
|
||||
<el-button @click="methods.viewProduct(row)" size="small">
|
||||
零售清单</el-button
|
||||
>
|
||||
<el-button @click="methods.print(row)" size="small"
|
||||
>打印</el-button
|
||||
>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<retailList v-model="showDialog" :option="retailListTable"></retailList>
|
||||
|
||||
<baseDialog
|
||||
v-model="retailRegisState.showDialog"
|
||||
top="50px"
|
||||
title="零售结算">
|
||||
<retailRegis
|
||||
v-model="regisForm"
|
||||
:retailType="searchForm.retail.retailType"
|
||||
:showServiceDelBtn="handlerType !== 'view'"
|
||||
:add="handlerType === 'add'"
|
||||
type="零售结算"></retailRegis>
|
||||
<template #footer>
|
||||
<el-row justify="center" align="middle" style="margin-top: 15px">
|
||||
<el-button type="danger" @click="methods.close">关闭</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
</baseDialog>
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="70%"
|
||||
:before-close="methods.handleDialogClose"
|
||||
@addConfim="methods.addConfim"
|
||||
@closeConfirm="methods.handleDialogClose"
|
||||
confirmText="结账"
|
||||
destroy-on-close
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<checkoutAddOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
:deceased="currentData"
|
||||
v-model="currentPayment">
|
||||
</checkoutAddOrEdit>
|
||||
</template>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="methods.addConfim"
|
||||
>确定结账</el-button
|
||||
></template
|
||||
>
|
||||
</base-curd-dialog>
|
||||
|
||||
<printServicesPage
|
||||
v-model="showPrint"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</printServicesPage>
|
||||
|
||||
<base-dialog
|
||||
v-model="cancelState.showDialog"
|
||||
title="账单作废"
|
||||
width="50%"
|
||||
@closeConfirm="methods.cancleClose">
|
||||
<el-form :model="cancelForm" label-width="120px" style="padding: 20px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<!-- 注销申请人 -->
|
||||
<el-form-item label="作废申请人">
|
||||
<el-input disabled v-model="cancelForm.cancelPerson" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<!-- 注销日期 -->
|
||||
<el-form-item label="作废日期">
|
||||
<el-date-picker
|
||||
disabled
|
||||
v-model="cancelForm.cancelDate"
|
||||
type="date" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<!-- 注销原因 -->
|
||||
<el-form-item label="作废原因">
|
||||
<el-input
|
||||
v-model="cancelForm.cancelReason"
|
||||
type="textarea"
|
||||
placeholder="请输入作废原因" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="flex-center">
|
||||
<el-button type="primary" @click="methods.submitCancel"
|
||||
>作废</el-button
|
||||
>
|
||||
<el-button @click="methods.resetCancel">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch, nextTick } from "vue";
|
||||
import { dayjs, ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import { globalState } from "@/store";
|
||||
import retailRegis from "../publicComponents/retailRegis.vue";
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { useRoute } from "vue-router";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import checkoutAddOrEdit from "./page/checkoutAddOrEdit.vue";
|
||||
import printServicesPage from "@/components/printPage/printServicesPage.vue";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import GuideList from "@/components/guideList/guideList.vue";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "结账登记",
|
||||
edit: "登记修改",
|
||||
view: "查看登记",
|
||||
});
|
||||
|
||||
let retailListTable = ref<tableOptionType>({
|
||||
url: "/deceased-retail/selected-service",
|
||||
searchUrl: "",
|
||||
searchParams: {},
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
const retailRegisState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
|
||||
let currentRetail = ref<RegisForm>(defaultRetail());
|
||||
|
||||
let currentInfor = ref(undefined);
|
||||
let showDialog = ref(false);
|
||||
|
||||
let showPrint = ref(false);
|
||||
let deceased = ref();
|
||||
let serviceUrl = ref();
|
||||
|
||||
const handlerType = ref("");
|
||||
const searchForm = ref({
|
||||
retail: {
|
||||
guide: "", // 引导员
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
purchaseDate: ["", ""],
|
||||
retailType: 1,
|
||||
familyName: "",
|
||||
},
|
||||
deceased: {
|
||||
name: "", // 逝者姓名
|
||||
familyName: "",
|
||||
},
|
||||
});
|
||||
|
||||
let currentPayment = ref<PaymentForm>(defaultPaymentForm());
|
||||
let currentData = ref();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const regisForm = ref<RegisForm>();
|
||||
const cancelState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
const globaUser = userInfor().userInfor;
|
||||
const cancelForm = ref({
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
});
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/deceased-retail/list?retailType=" + searchForm.value.retail.retailType,
|
||||
searchUrl: "/deceased-retail/query",
|
||||
searchParams: searchForm.value,
|
||||
executeType: "list",
|
||||
});
|
||||
const methods = {
|
||||
add() {
|
||||
retailRegisState.value.showDialog = true;
|
||||
handlerType.value = "add";
|
||||
},
|
||||
cancel(row: RegisForm) {
|
||||
currentRetail.value = row;
|
||||
cancelState.value.showDialog = true;
|
||||
},
|
||||
viewProduct(row: RegisForm) {
|
||||
retailListTable.value.url =
|
||||
"/deceased-retail/selected-service?retailId=" + row.id;
|
||||
showDialog.value = true;
|
||||
},
|
||||
drawerClose() {
|
||||
currentInfor.value = undefined;
|
||||
showDialog.value = false;
|
||||
},
|
||||
async checkout(row: RegisForm) {
|
||||
currentData.value = row;
|
||||
pageVisibleState.dialogTitle.value = "零售结算";
|
||||
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
},
|
||||
async hanlderView(row: RegisForm) {
|
||||
// await ElMessageBox.confirm("确定结账吗?");
|
||||
regisForm.value = row;
|
||||
retailRegisState.value.showDialog = true;
|
||||
handlerType.value = "view";
|
||||
|
||||
pageVisibleState.dialogTitle.value = "零售查看";
|
||||
},
|
||||
close() {
|
||||
retailRegisState.value.showDialog = false;
|
||||
},
|
||||
async cancle() {
|
||||
await ElMessageBox.confirm("确定作废该条吗?", { type: "error" });
|
||||
retailRegisState.value.showDialog = false;
|
||||
ElMessage.success("作废成功!");
|
||||
},
|
||||
print(row: RegisForm) {
|
||||
deceased.value = row;
|
||||
serviceUrl.value = `/deceased-retail/selected-service?retailType=${searchForm.value.retail.retailType}&retailId=${row.id}`;
|
||||
|
||||
nextTick(() => {
|
||||
showPrint.value = true;
|
||||
});
|
||||
},
|
||||
search() {
|
||||
table.value.methods.setDataType("search");
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
searchForm.value = {
|
||||
retail: {
|
||||
guide: "", // 引导员
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
purchaseDate: ["", ""],
|
||||
retailType: 1,
|
||||
familyName: "",
|
||||
},
|
||||
deceased: {
|
||||
name: "", // 逝者姓名
|
||||
familyName: "",
|
||||
},
|
||||
};
|
||||
tableOption.value.searchParams = searchForm.value;
|
||||
nextTick(() => {
|
||||
table.value.methods.setDataType("search");
|
||||
});
|
||||
},
|
||||
|
||||
async addConfim() {
|
||||
await ElMessageBox.confirm("确定结账吗?", { type: "warning" });
|
||||
|
||||
let sendData = {
|
||||
deceased: {
|
||||
...currentData.value,
|
||||
},
|
||||
currentPayment: {
|
||||
...currentPayment.value,
|
||||
},
|
||||
id: currentData.value.id,
|
||||
};
|
||||
let url = "/checkout/deceasedCheckout";
|
||||
|
||||
const res = await api().post(url, sendData);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("结账成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
nextTick(() => {
|
||||
table.value.methods.setDataType("search");
|
||||
currentPayment.value = defaultPaymentForm();
|
||||
currentData.value = undefined;
|
||||
});
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
},
|
||||
|
||||
handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
currentData.value = undefined;
|
||||
currentPayment.value = defaultPaymentForm();
|
||||
},
|
||||
cancleClose() {
|
||||
cancelForm.value = {
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
};
|
||||
},
|
||||
|
||||
async submitCancel() {
|
||||
if (!cancelForm.value.cancelReason) {
|
||||
return ElMessage.error("请输入作废原因");
|
||||
}
|
||||
await ElMessageBox.confirm("确定作废吗?", { type: "warning" });
|
||||
|
||||
let sendData = {
|
||||
deceasedRetailId: currentRetail.value.id,
|
||||
cancelForm: { ...cancelForm.value },
|
||||
cancelType: 0,
|
||||
};
|
||||
|
||||
api()
|
||||
.post("/cancel/cancel", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("作废提交成功!");
|
||||
methods.resetCancel();
|
||||
cancelForm.value = {
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
};
|
||||
table.value.methods.setDataType("search");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
resetCancel() {
|
||||
cancelForm.value = {
|
||||
cancelPerson: globaUser.name,
|
||||
cancelDate: dayjs().format(),
|
||||
cancelReason: "",
|
||||
};
|
||||
cancelState.value.showDialog = false;
|
||||
},
|
||||
};
|
||||
|
||||
watch(
|
||||
() => searchForm.value.retail.retailType,
|
||||
() => {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
);
|
||||
|
||||
function dataChange(val: Date[]) {
|
||||
searchForm.value.retail.startDate = val[0];
|
||||
searchForm.value.retail.endDate = val[1];
|
||||
}
|
||||
|
||||
const getSummaries = (param: { columns: any[]; data: any[] }) => {
|
||||
const { columns, data } = param;
|
||||
const sums: any[] = [];
|
||||
// 需要统计的字段列表
|
||||
const sumKeys = [
|
||||
"salesAmount",
|
||||
"payment.cashAmount",
|
||||
"payment.unionPayAmount",
|
||||
"payment.cardAmount",
|
||||
"payment.publicTransferAmount",
|
||||
"payment.workshopPayment",
|
||||
];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计";
|
||||
return;
|
||||
}
|
||||
if (sumKeys.includes(column.property)) {
|
||||
const values = data.map((item) => {
|
||||
const keys = column.property.split(".");
|
||||
let value = item;
|
||||
for (const key of keys) {
|
||||
value = value?.[key] || 0;
|
||||
}
|
||||
return Number(value) || 0;
|
||||
});
|
||||
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
const sum = values.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
sums[index] = `${sum.toFixed(2)}`;
|
||||
} else {
|
||||
sums[index] = "0.00 元";
|
||||
}
|
||||
} else {
|
||||
sums[index] = "";
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
/* 添加汇总行样式 */
|
||||
:deep(.el-table__footer) {
|
||||
.cell {
|
||||
font-weight: 600;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
460
frontEnd/src/pages/funeralServices/funeralServices.vue
Normal file
460
frontEnd/src/pages/funeralServices/funeralServices.vue
Normal file
@@ -0,0 +1,460 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="殡仪服务"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form
|
||||
:model="searchForm"
|
||||
:inline="true"
|
||||
label-position="right"
|
||||
label-width="80px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入逝者姓名"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="searchForm.gender">
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人">
|
||||
<el-input
|
||||
v-model="searchForm.familyName"
|
||||
placeholder="请输入购买人姓名"></el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人手机号">
|
||||
<el-input
|
||||
v-model="searchForm.familyPhone"
|
||||
placeholder="请输入购买人手机号"></el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6"
|
||||
><el-form-item label="引导员">
|
||||
<GuideList
|
||||
v-model="searchForm.guide"></GuideList> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="录单日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.createDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="录单日期" /> </el-form-item
|
||||
></el-col>
|
||||
<!-- <el-col :span="6">
|
||||
<el-form-item label="结账日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.checkoutDate"
|
||||
type="date"
|
||||
placeholder="结账日期" /></el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="录单日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.purchaseDate"
|
||||
type="datetime"
|
||||
placeholder="录单日期" /></el-form-item
|
||||
></el-col> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table :option="tableOption" ref="table" border>
|
||||
<template #toolsBar>
|
||||
<el-button size="small" type="primary" @click="methods.handleService">
|
||||
服务办理</el-button
|
||||
>
|
||||
</template>
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="60"
|
||||
label="序号"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="逝者姓名"
|
||||
align="center" />
|
||||
<el-table-column prop="deceased.gender" label="性别" align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.age"
|
||||
label="年龄"
|
||||
width="80"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.familyName"
|
||||
label="购买人姓名"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.familyPhone"
|
||||
label="购买人手机号"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column prop="deceased.name" label="购买人" align="center" />
|
||||
<el-table-column
|
||||
prop="retail.purchaseDate"
|
||||
label="录单日期"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column prop="handler" label="经办人" align="center" />
|
||||
<el-table-column
|
||||
prop="retail.salesAmount"
|
||||
label="销售金额"
|
||||
align="center"
|
||||
width="180">
|
||||
<template #default="{ row }">
|
||||
{{ row.retail.salesAmount || 0 }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="guide"
|
||||
label="引导员"
|
||||
width="120"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="350"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.addRetailRegis(row)">
|
||||
零售登记
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.retail?.retailState !== 1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="methods.update(row)">
|
||||
修改</el-button
|
||||
>
|
||||
|
||||
<el-button @click="methods.viewProduct(row)" size="small">
|
||||
服务清单</el-button
|
||||
>
|
||||
<el-button size="small" type="default" @click="methods.print(row)"
|
||||
>打印</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<baseDialog
|
||||
v-model="retailRegisState.showAddRetial"
|
||||
top="50px"
|
||||
:title="retailTitle"
|
||||
@close="methods.addRetialClose">
|
||||
<retailRegis
|
||||
v-model="retailRegisForm"
|
||||
:type="retailRegisState.type"
|
||||
:showList="['逝者信息']"></retailRegis>
|
||||
<template #footer>
|
||||
<el-row justify="center" align="middle" style="margin-top: 15px">
|
||||
<el-button type="primary" @click="methods.addConfim">保存</el-button>
|
||||
<el-button type="danger" @click="methods.addClose">关闭</el-button>
|
||||
</el-row>
|
||||
</template>
|
||||
</baseDialog>
|
||||
|
||||
<baseDialog
|
||||
v-model="retailRegisState.showUpdateDialog"
|
||||
top="50px"
|
||||
:title="retailRegisState.title"
|
||||
@close="methods.resetRegisForm">
|
||||
<div
|
||||
v-loading="retailRegisState.showLoding"
|
||||
element-loading-text="正在处理...">
|
||||
<retailRegis
|
||||
v-model="regisForm"
|
||||
:type="retailRegisState.type"
|
||||
:showList="['逝者信息']"></retailRegis>
|
||||
|
||||
<el-row :justify="'center'">
|
||||
<el-button type="primary" @click="methods.addConfim">确定</el-button>
|
||||
<el-button type="warning" @click="methods.updateClose"
|
||||
>关闭</el-button
|
||||
>
|
||||
</el-row>
|
||||
</div>
|
||||
</baseDialog>
|
||||
|
||||
<PrintRetailPage
|
||||
v-model="showPrint"
|
||||
:deceased="deceased"
|
||||
:serviceUrl="serviceUrl">
|
||||
</PrintRetailPage>
|
||||
|
||||
<retailList
|
||||
v-model="showRetailList"
|
||||
title="服务清单"
|
||||
:option="retailListTable"></retailList>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import retailRegis from "../funeralRetail/publicComponents/retailRegis.vue";
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import PrintRetailPage from "@/components/printPage/printRetailPage.vue";
|
||||
import GuideList from "@/components/guideList/guideList.vue";
|
||||
|
||||
interface deceasedForm extends RegisForm {
|
||||
deceased: RegisForm;
|
||||
retailType: number;
|
||||
}
|
||||
|
||||
const retailRegisState = ref({
|
||||
showAddRetial: false,
|
||||
title: "服务登记",
|
||||
type: "服务登记" as RegistrationType,
|
||||
showLoding: false,
|
||||
showUpdateDialog: false,
|
||||
});
|
||||
const serviceState = ref({
|
||||
showDialog: false,
|
||||
});
|
||||
|
||||
let showRetailList = ref(false);
|
||||
|
||||
let retailTitle = ref("服务登记");
|
||||
|
||||
let showPrint = ref(false);
|
||||
let deceased = ref();
|
||||
let serviceUrl = ref();
|
||||
|
||||
let retailListTable = ref<tableOptionType>({
|
||||
url: "/deceased-retail/selected-service",
|
||||
searchUrl: "",
|
||||
searchParams: {},
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
const searchForm = reactive({
|
||||
name: "", // 逝者姓名
|
||||
gender: "", // 性别
|
||||
phone: "", // 手机号
|
||||
guide: "", // 引导员
|
||||
purchaseDate: "", // 购买日期
|
||||
createDate: "",
|
||||
familyName: "",
|
||||
familyPhone: "",
|
||||
});
|
||||
|
||||
const regisForm = ref<deceasedForm>(defaultRetail());
|
||||
const retailRegisForm = ref<RegisForm>(defaultRetail());
|
||||
|
||||
let table = ref();
|
||||
const tableOption = ref<tableOptionType>({
|
||||
url: "/deceased/list", // 获取列表数据的接口
|
||||
searchUrl: "/deceased/query", // 搜索接口
|
||||
searchParams: searchForm, // 搜索表单数据
|
||||
executeType: "list", // 默认执行类型
|
||||
});
|
||||
|
||||
const methods = {
|
||||
// 零售登记
|
||||
addRetailRegis(item: RegisForm) {
|
||||
retailRegisForm.value = {
|
||||
...regisForm.value,
|
||||
...item,
|
||||
serviceItems: [],
|
||||
services: [],
|
||||
};
|
||||
retailRegisState.value.title = "零售登记";
|
||||
retailRegisState.value.type = "零售登记";
|
||||
retailRegisState.value.showAddRetial = true;
|
||||
retailTitle.value = "零售登记";
|
||||
},
|
||||
|
||||
async print(row: any) {
|
||||
deceased.value = row;
|
||||
showPrint.value = true;
|
||||
|
||||
serviceUrl.value =
|
||||
"/deceased-retail/selected-service?retailType=0&deceasedId=" + row.id;
|
||||
},
|
||||
drawerClose() {
|
||||
showRetailList.value = false;
|
||||
},
|
||||
|
||||
async viewProduct(row: RegisForm) {
|
||||
retailListTable.value.url =
|
||||
"/deceased-retail/selected-service?retailType=0&deceasedId=" + row.id;
|
||||
showRetailList.value = true;
|
||||
},
|
||||
|
||||
update(row: RegisForm) {
|
||||
regisForm.value = row;
|
||||
retailTitle.value = "服务修改";
|
||||
retailRegisState.value.title = "服务修改";
|
||||
retailRegisState.value.type = "服务修改";
|
||||
retailRegisState.value.showUpdateDialog = true;
|
||||
},
|
||||
|
||||
// 服务办理
|
||||
handleService() {
|
||||
retailRegisForm.value = defaultRetail();
|
||||
serviceState.value.showDialog = true;
|
||||
retailRegisState.value.showAddRetial = true;
|
||||
retailRegisState.value.title = "服务登记";
|
||||
retailRegisState.value.type = "服务登记";
|
||||
retailTitle.value = "服务登记";
|
||||
},
|
||||
|
||||
// 重置登记表单
|
||||
resetRegisForm() {
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
|
||||
// 取消操作
|
||||
cancle() {
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
methods.resetRegisForm();
|
||||
},
|
||||
|
||||
updateClose() {
|
||||
retailRegisState.value.showUpdateDialog = false;
|
||||
},
|
||||
addClose() {
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
|
||||
async confirmUpdate() {
|
||||
await ElMessageBox.confirm("确定保存修改吗?", { type: "warning" });
|
||||
let sendData = { ...regisForm.value };
|
||||
api()
|
||||
.post("/deceased-retail/update", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("修改成功");
|
||||
table.value.methods.setDataType("list");
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
regisForm.value = defaultRetail();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async addConfim() {
|
||||
if (retailRegisState.value.type === "服务登记") {
|
||||
if (!retailRegisForm.value.idNumber || !retailRegisForm.value.name) {
|
||||
return ElMessage.error("逝者姓名和证件号码不能为空!");
|
||||
}
|
||||
}
|
||||
|
||||
let confirmContent = "";
|
||||
if (retailRegisState.value.type === "服务登记")
|
||||
confirmContent = "确定登记该服务吗?";
|
||||
if (retailRegisState.value.type === "零售登记")
|
||||
confirmContent = "确定登记该信息吗?";
|
||||
if (retailRegisState.value.type === "服务修改")
|
||||
confirmContent = "确定修改该信息吗?";
|
||||
|
||||
await ElMessageBox.confirm(confirmContent, "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (retailRegisState.value.type === "服务登记") {
|
||||
let sendData = { ...retailRegisForm.value };
|
||||
sendData.retailType = 0;
|
||||
api()
|
||||
.post("/deceased/add", sendData) // 修改为 Deceased 的接口
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("新增成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
retailRegisState.value.showLoding = false;
|
||||
methods.resetRegisForm();
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (retailRegisState.value.type === "零售登记") {
|
||||
let sendData = { ...retailRegisForm.value };
|
||||
sendData.retailType = 1;
|
||||
|
||||
sendData.deceasedId = sendData.id;
|
||||
|
||||
let url = "/deceased-retail/add?type=1";
|
||||
|
||||
api()
|
||||
.post(url, sendData) // 修改为 Deceased 的接口
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("新增成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
retailRegisState.value.showLoding = false;
|
||||
methods.resetRegisForm();
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (retailRegisState.value.type === "服务修改") {
|
||||
let sendData = { ...regisForm.value };
|
||||
sendData.retailType = 0;
|
||||
sendData.deceased.familyName = sendData.familyName;
|
||||
sendData.deceased.familyPhone = sendData.familyPhone;
|
||||
sendData.deceased.address = sendData.address;
|
||||
sendData.deceased.area = sendData.area;
|
||||
sendData.deceased.province = sendData.province;
|
||||
sendData.deceased.city = sendData.city;
|
||||
sendData.deceased.guide = sendData.guide;
|
||||
api()
|
||||
.post("/deceased-retail/updateRetail", sendData) // 修改为 Deceased 的接口
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("修改成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
retailRegisState.value.showLoding = false;
|
||||
retailRegisState.value.showUpdateDialog = false;
|
||||
|
||||
methods.resetRegisForm();
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
addRetialClose() {
|
||||
retailRegisState.value.showAddRetial = false;
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
};
|
||||
|
||||
onMounted(async () => {});
|
||||
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("reset");
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
143
frontEnd/src/pages/funeralServices/page/userAddOrEdit.vue
Normal file
143
frontEnd/src/pages/funeralServices/page/userAddOrEdit.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<el-form
|
||||
:model="user"
|
||||
label-width="100px"
|
||||
:inline="true"
|
||||
label-suffix=":"
|
||||
v-loading="loading"
|
||||
element-loading-text="正在初始化数据...">
|
||||
<el-form-item label="姓名">
|
||||
<el-input :prefix-icon="User" v-model="user.name" placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="user.sex">
|
||||
<el-radio value="男">男</el-radio>
|
||||
<el-radio value="女">女</el-radio>
|
||||
<el-radio value="保密">保密</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="电话">
|
||||
<el-input
|
||||
:prefix-icon="Iphone"
|
||||
v-model="user.phone"
|
||||
placeholder="电话"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属角色">
|
||||
<el-select
|
||||
v-model="user.role"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择角色"
|
||||
style="width: 230px">
|
||||
<el-option
|
||||
v-for="item in roleList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="String(item.id)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="生日">
|
||||
<el-date-picker
|
||||
format="YYYYH-MM-DD"
|
||||
v-model="user.birthday"
|
||||
type="date"
|
||||
placeholder="生日"
|
||||
size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所在区域">
|
||||
<el-cascader
|
||||
:options="pcaTextArrData"
|
||||
v-model="selectedOptions"
|
||||
@change="pcaChange"></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址">
|
||||
<el-input
|
||||
:prefix-icon="Location"
|
||||
v-model="user.address"
|
||||
placeholder="请输入详细地址"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="账号状态">
|
||||
<el-switch
|
||||
v-model="user.userState"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="启用"
|
||||
width="65px"
|
||||
inline-prompt
|
||||
inactive-text="禁用"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { userType } from "@/types/user";
|
||||
// @ts-ignore
|
||||
import { pcaTextArr } from "element-china-area-data";
|
||||
import { Avatar, Location, Iphone, User } from "@element-plus/icons-vue";
|
||||
import { roleType } from "@/types/role";
|
||||
import { roleDataList } from "@/lib/api/publicApiList";
|
||||
|
||||
const pcaTextArrData = ref(pcaTextArr);
|
||||
const selectedOptions = ref([]);
|
||||
const props = defineProps<{
|
||||
data?: userType;
|
||||
executeType?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["updateData"]);
|
||||
|
||||
let loading = ref(true);
|
||||
let roleList = ref<roleType[]>();
|
||||
let user = ref<userType>({
|
||||
createDate: "",
|
||||
name: "",
|
||||
sex: "男",
|
||||
phone: "",
|
||||
userState: 1,
|
||||
role: "",
|
||||
birthday: "",
|
||||
province: "",
|
||||
city: "",
|
||||
area: "",
|
||||
address: "",
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
roleList.value = await roleDataList();
|
||||
|
||||
watch(
|
||||
() => user,
|
||||
(newVal) => {
|
||||
emit("updateData", newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
if (props.executeType === "edit") {
|
||||
user.value = { ...props.data };
|
||||
selectedOptions.value = [
|
||||
user.value.province as never,
|
||||
user.value.city as never,
|
||||
user.value.area as never,
|
||||
];
|
||||
}
|
||||
|
||||
function pcaChange(data: { [key: string]: any }) {
|
||||
user.value.province = data[0];
|
||||
user.value.city = data[1];
|
||||
user.value.area = data[2];
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-input) {
|
||||
width: 230px;
|
||||
}
|
||||
:deep(.el-form-item) {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
374
frontEnd/src/pages/invalidReview/invalidReview.vue
Normal file
374
frontEnd/src/pages/invalidReview/invalidReview.vue
Normal file
@@ -0,0 +1,374 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="作废审核"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form
|
||||
:model="searchForm"
|
||||
label-position="right"
|
||||
label-width="90px">
|
||||
<el-row :gutter="15">
|
||||
<!-- 逝者姓名 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入逝者姓名" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 作废申请人 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="作废申请人" style="width: 100%">
|
||||
<el-select
|
||||
v-model="searchForm.cancelPerson"
|
||||
placeholder="请选择申请人">
|
||||
<el-option
|
||||
v-for="item in guideOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 结账时间 -->
|
||||
<!-- <el-col :span="6">
|
||||
<el-form-item label="结账时间">
|
||||
<el-date-picker
|
||||
value-format="YYYY-MM-DD"
|
||||
v-model="searchForm.checkoutDate"
|
||||
type="date"
|
||||
placeholder="选择结账时间"
|
||||
format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
|
||||
<!-- 申请时间 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="申请时间">
|
||||
<el-date-picker
|
||||
value-format="YYYY-MM-DD"
|
||||
v-model="searchForm.cancelDate"
|
||||
type="date"
|
||||
placeholder="选择申请时间"
|
||||
format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table :option="tableOption" ref="table" border>
|
||||
<template #toolsBar>
|
||||
<el-radio-group v-model="searchForm.examineState" size="small">
|
||||
<el-radio-button :value="0" label="未处理"></el-radio-button>
|
||||
<el-radio-button :value="1" label="已通过"></el-radio-button>
|
||||
<!-- <el-radio-button :value="2" label="已拒绝"></el-radio-button> -->
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template #colunm>
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="80"
|
||||
align="center" />
|
||||
|
||||
<!-- 状态 -->
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" v-if="row.examineState === 0"
|
||||
>未审核</el-tag
|
||||
>
|
||||
<el-tag type="success" v-if="row.examineState === 1"
|
||||
>已审核</el-tag
|
||||
>
|
||||
<el-tag type="success" v-if="row.examineState === 2"
|
||||
>已拒绝</el-tag
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="逝者姓名" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retail.retailType !== 2">
|
||||
{{ row.deceased.name }}</span
|
||||
>
|
||||
<span v-else> {{ row.retail.familyName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="deceased.gender" label="性别" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retail.retailType !== 2">
|
||||
{{ row.deceased.gender }}</span
|
||||
>
|
||||
<span v-else> {{ row.retail.gender || "无" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.age"
|
||||
label="年龄"
|
||||
width="80"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row.retail.retailType !== 2">
|
||||
{{ row.deceased.age }}</span
|
||||
>
|
||||
<span v-else> {{ row.retail.age || "无" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="cancelReason"
|
||||
label="作废原因"
|
||||
width="200"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="cancelPerson"
|
||||
label="作废申请人"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="cancelDate"
|
||||
label="申请时间"
|
||||
align="center"
|
||||
width="180" />
|
||||
<el-table-column
|
||||
prop="retail.checkoutDate"
|
||||
label="结账时间"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column
|
||||
prop="payment.cashAmount"
|
||||
label="现金支付"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cashAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.unionPayAmount"
|
||||
label="银联支付"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.unionPayAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="payment.cardAmount"
|
||||
label="刷卡金额"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.cardAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.publicTransferAmount"
|
||||
label="对公转账"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.publicTransferAmount || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payment.workshopPayment"
|
||||
label="车间支付"
|
||||
width="100"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.payment?.workshopPayment || "0.00" }} 元
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
width="200"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
v-if="row.examineState === 0"
|
||||
@click="methods.invalid(row)">
|
||||
审核</el-button
|
||||
>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
v-if="row.examineState === 1"
|
||||
@click="methods.view(row)">
|
||||
查看</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<baseDialog
|
||||
v-model="invalidReviewState.showDialog"
|
||||
top="50px"
|
||||
:title="invalidReviewState.title"
|
||||
@close="methods.resetRegisForm">
|
||||
<div
|
||||
v-loading="invalidReviewState.showLoding"
|
||||
element-loading-text="正在处理...">
|
||||
<reviewDetails v-model="currentData"></reviewDetails>
|
||||
|
||||
<el-row :justify="'center'">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="methods.confirm"
|
||||
v-if="invalidReviewState.title !== '作废查看'"
|
||||
>确定</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="invalidReviewState.title !== '作废查看'"
|
||||
@click="methods.cancel"
|
||||
>拒绝</el-button
|
||||
>
|
||||
<el-button type="danger" @click="methods.close">关闭</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</baseDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import { globalState } from "@/store";
|
||||
import reviewDetails from "./reviewDetails.vue";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import api from "@/lib/request";
|
||||
|
||||
const invalidReviewState = ref({
|
||||
showDialog: false,
|
||||
title: "作废审核",
|
||||
type: "服务登记" as RegistrationType,
|
||||
showLoding: false,
|
||||
});
|
||||
|
||||
const guideOptions = ref<guideOption[]>([]);
|
||||
|
||||
const searchForm = reactive({
|
||||
examineState: 0, // 状态
|
||||
name: "", // 逝者姓名
|
||||
cancelPerson: "", // 作废申请人
|
||||
checkoutDate: "", // 结账时间
|
||||
cancelDate: "", // 申请时间
|
||||
});
|
||||
|
||||
const currentData = ref({
|
||||
payment: defaultPaymentForm(),
|
||||
deceased: {},
|
||||
retail: defaultRetail(),
|
||||
});
|
||||
|
||||
const regisForm = ref<RegisForm>(defaultRetail());
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/cancel/list",
|
||||
searchUrl: "/cancel/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
const methods = {
|
||||
resetRegisForm() {
|
||||
regisForm.value = defaultRetail();
|
||||
},
|
||||
async confirm() {
|
||||
let confirmContent = "确定【通过】该信息吗?";
|
||||
|
||||
await ElMessageBox.confirm(confirmContent, "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
let sendData = { ...currentData.value };
|
||||
sendData.examineState = 1;
|
||||
api()
|
||||
.post("/cancel/examine", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
invalidReviewState.value.showDialog = false;
|
||||
ElMessage.success("成功通过!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
invalid(row: any) {
|
||||
currentData.value = row;
|
||||
invalidReviewState.value.showDialog = true;
|
||||
invalidReviewState.value.title = "作废审核";
|
||||
},
|
||||
async cancel() {
|
||||
let confirmContent = "确定【拒绝】该信息吗?";
|
||||
await ElMessageBox.confirm(confirmContent, { type: "warning" });
|
||||
|
||||
let sendData = { ...currentData.value };
|
||||
sendData.examineState = 2;
|
||||
api()
|
||||
.post("/cancel/examine", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
invalidReviewState.value.showDialog = false;
|
||||
ElMessage.success("成功拒绝!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
invalidReviewState.value.showDialog = false;
|
||||
invalidReviewState.value.title = "";
|
||||
methods.resetRegisForm();
|
||||
},
|
||||
|
||||
view(row: any) {
|
||||
invalidReviewState.value.showDialog = true;
|
||||
currentData.value = row;
|
||||
invalidReviewState.value.title = "作废查看";
|
||||
},
|
||||
};
|
||||
api()
|
||||
.get("public/guide")
|
||||
.then((res) => {
|
||||
guideOptions.value = res.data;
|
||||
});
|
||||
onMounted(async () => {});
|
||||
|
||||
watch(
|
||||
() => searchForm.examineState,
|
||||
(newData) => {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
);
|
||||
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("reset");
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
259
frontEnd/src/pages/invalidReview/reviewDetails.vue
Normal file
259
frontEnd/src/pages/invalidReview/reviewDetails.vue
Normal file
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<el-form
|
||||
style="max-height: 72vh; overflow-y: auto"
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
label-width="120px"
|
||||
label-position="right">
|
||||
<inforCard title="逝者信息">
|
||||
<el-form :model="formData" label-width="120px" disabled>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="姓名">
|
||||
<el-input
|
||||
v-model="formData.deceased.name"
|
||||
disabled
|
||||
placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="formData.deceased.gender" disabled>
|
||||
<el-radio-button value="男" label="男"></el-radio-button>
|
||||
<el-radio-button value="女" label="女"></el-radio-button>
|
||||
</el-radio-group> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idNumber">
|
||||
<el-input v-model="formData.deceased.idNumber" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="年龄">
|
||||
<el-input
|
||||
v-model="formData.deceased.age"
|
||||
disabled
|
||||
placeholder="年龄">
|
||||
</el-input> </el-form-item
|
||||
></el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人姓名" prop="buyer">
|
||||
<el-input v-model="formData.deceased.familyName" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买人电话" prop="buyer">
|
||||
<el-input v-model="formData.deceased.familyPhone" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="购买日期" prop="purchaseDate">
|
||||
<el-date-picker
|
||||
v-model="formData.deceased.purchaseDate"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD: HH:mm:ss" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
|
||||
<inforCard title="结账列表">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
label-width="120px"
|
||||
label-position="right">
|
||||
<el-row :gutter="20">
|
||||
<!-- 第一行 -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结账日期" prop="checkoutDate">
|
||||
<el-date-picker
|
||||
v-model="formData.payment.checkoutDate"
|
||||
type="date"
|
||||
placeholder="结账日期"
|
||||
format="YYYY-MM-DD"
|
||||
disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker
|
||||
v-model="formData.payment.settlementDate"
|
||||
type="date"
|
||||
disabled
|
||||
placeholder="选择日期"
|
||||
format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人" prop="handler">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.handler"
|
||||
placeholder="经办人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="现金金额" prop="cash">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.cashAmount"
|
||||
:min="0"
|
||||
@change="caleValue('cashAmount')"
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银联" prop="unionPay">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.unionPayAmount"
|
||||
:min="0"
|
||||
@change="caleValue('cashAmount')"
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="银行卡" prop="cardPay">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.cardAmount"
|
||||
:min="0"
|
||||
@change="caleValue('cashAmount')"
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item label="对公" prop="transfer">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.publicTransferAmount"
|
||||
:min="0"
|
||||
@change="caleValue('cashAmount')"
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="车间支付" prop="transfer">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.payment.workshopPayment"
|
||||
:min="0"
|
||||
@change="caleValue('cashAmount')"
|
||||
type="number">
|
||||
<template #append>元</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</inforCard>
|
||||
|
||||
<inforCard title="作废信息">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="作废申请人">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.cancelPerson"
|
||||
placeholder="请输入作废申请人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="作废时间">
|
||||
<el-date-picker
|
||||
disabled
|
||||
v-model="formData.cancelDate"
|
||||
type="datetime"
|
||||
placeholder="选择作废时间" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="作废原因">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.cancelReason"
|
||||
type="textarea"
|
||||
placeholder="请输入作废原因" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</inforCard>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { defaultPaymentForm } from "@/defaultForm/defaultPaymentForm";
|
||||
import { defaultRetail } from "@/defaultForm/defaultRetail";
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
// 表单数据
|
||||
const formData = defineModel<any>({
|
||||
default: {
|
||||
payment: defaultPaymentForm(),
|
||||
deceased: {},
|
||||
retail: defaultRetail(),
|
||||
},
|
||||
});
|
||||
|
||||
if (!formData.value.payment) {
|
||||
formData.value.payment = defaultPaymentForm();
|
||||
}
|
||||
if (!formData.value.deceased) {
|
||||
formData.value.deceased = { ...formData.value.retail };
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
add?: boolean;
|
||||
type?: "审核" | "申请";
|
||||
}>(),
|
||||
{
|
||||
add: false,
|
||||
type: "审核",
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {});
|
||||
|
||||
let keys = [
|
||||
"cashAmount",
|
||||
"unionPayAmount",
|
||||
"cardAmount",
|
||||
"publicTransferAmount",
|
||||
"workshopPayment",
|
||||
];
|
||||
|
||||
function caleValue(keyVal: string) {
|
||||
let total = 0;
|
||||
let currentVal = formData.value.payment[keyVal];
|
||||
|
||||
keys.forEach((key) => {
|
||||
if (keyVal !== key) {
|
||||
let tempVal = Number(formData.value.payment[key]).toFixed(2);
|
||||
total = Number(total) + Number(tempVal);
|
||||
}
|
||||
});
|
||||
let salesAmount = Number(formData.value.deceased.salesAmount);
|
||||
|
||||
if (salesAmount - (total + currentVal) < 0) {
|
||||
formData.value[keyVal] = salesAmount - total;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
BIN
frontEnd/src/pages/login/img/login-bck.jpg
Normal file
BIN
frontEnd/src/pages/login/img/login-bck.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 758 KiB |
123
frontEnd/src/pages/login/login.vue
Normal file
123
frontEnd/src/pages/login/login.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div
|
||||
class="logon-main-content"
|
||||
v-loading="loading"
|
||||
:element-loading-text="'正在登录...'">
|
||||
<div class="login">
|
||||
<h2 class="title">欢迎使用德孝善延伸服务系统</h2>
|
||||
<el-form :model="data.loginForm" class="login-form">
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="data.loginForm.name"
|
||||
placeholder="请输入账户"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="data.loginForm.pwd"
|
||||
type="password"
|
||||
placeholder="请输入密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="">
|
||||
<el-button class="login-btn" type="default" @click="login"
|
||||
>登陆</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onBeforeMount, onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import MD5 from "js-md5";
|
||||
import api from "@/lib/request";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
const data = reactive({
|
||||
name: "测试",
|
||||
loginForm: {
|
||||
name: "",
|
||||
pwd: "",
|
||||
},
|
||||
});
|
||||
|
||||
let loading = ref(false);
|
||||
|
||||
const router = useRouter();
|
||||
const userInforState = userInfor();
|
||||
|
||||
onBeforeMount(() => {});
|
||||
|
||||
onMounted(() => {});
|
||||
|
||||
function login() {
|
||||
loading.value = true;
|
||||
api()
|
||||
.post("/login", {
|
||||
name: data.loginForm.name,
|
||||
pwd: MD5.md5(data.loginForm.pwd).toLocaleUpperCase(),
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res.code === 200) {
|
||||
userInforState.setLoginState(res.data.user);
|
||||
ElMessage.success("登录成功!");
|
||||
let userRouter: [] = res.data.user.routerMenue;
|
||||
let noChildren = userRouter.find((item) => !item.children.length);
|
||||
|
||||
router.replace({ name: noChildren.name });
|
||||
userInforState.setToken(res.data.token);
|
||||
userInforState.setRefToken(res.data.refreshToken);
|
||||
} else {
|
||||
ElMessage.error(res.msg || res);
|
||||
}
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.logon-main-content {
|
||||
background-image: url("./img/login-bck.jpg");
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
.login {
|
||||
width: 40%;
|
||||
height: 60%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
background-image: linear-gradient(135deg, #5efce8 10%, #736efe 100%);
|
||||
|
||||
.title {
|
||||
margin: 30px 0;
|
||||
font-size: 30px;
|
||||
}
|
||||
.copy-info {
|
||||
text-align: center;
|
||||
p {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
167
frontEnd/src/pages/main/index.vue
Normal file
167
frontEnd/src/pages/main/index.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row class="width-100" justify="space-between">
|
||||
<el-row :gutter="20" class="width-100">
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<el-row :gutter="15" justify="space-between">
|
||||
<el-col :span="12">
|
||||
<h2>框架访问人数</h2>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<h1>100</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
今天的天气也很好呀
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<el-row :gutter="15" justify="space-between">
|
||||
<el-col :span="12">
|
||||
<h2>留言总数</h2>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<h1>3205</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
每一天都有希望
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<el-row :gutter="15" justify="space-between">
|
||||
<el-col :span="12">
|
||||
<h2>用户数量</h2>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<h1>421</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
期待美好的事情发生
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<el-row :gutter="15" justify="space-between">
|
||||
<el-col :span="12">
|
||||
<h2>总文章数</h2>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<h1>421</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
明天将会发生什么呢
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row>
|
||||
|
||||
<el-row style="margin-top: 15px" :gutter="20" class="width-100">
|
||||
<el-col :span="18" style="height: 500px">
|
||||
<el-card class="height-100" body-style="height:100%">
|
||||
<baseEcharts></baseEcharts>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card style="height: 500px; overflow-y: auto">
|
||||
<template #header> 更新动态 </template>
|
||||
<p v-for="i in 20" :key="i">今天这里是第{{ i }}篇文章</p>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="24" style="margin-top: 15px">
|
||||
<el-card>
|
||||
<baseEcharts :option="lineStack" style="height: 500px"></baseEcharts>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from "vue";
|
||||
import baseEcharts from "@/components/baseEcharts/baseEcharts.vue";
|
||||
|
||||
const data = reactive({});
|
||||
const lineStack = reactive({
|
||||
title: {
|
||||
text: "Stacked Line",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
legend: {
|
||||
data: ["Email", "Union Ads", "Video Ads", "Direct", "Search Engine"],
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "4%",
|
||||
bottom: "3%",
|
||||
containLabel: true,
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {},
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Email",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [120, 132, 101, 134, 90, 230, 210],
|
||||
},
|
||||
{
|
||||
name: "Union Ads",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [220, 182, 191, 234, 290, 330, 310],
|
||||
},
|
||||
{
|
||||
name: "Video Ads",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [150, 232, 201, 154, 190, 330, 410],
|
||||
},
|
||||
{
|
||||
name: "Direct",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [320, 332, 301, 334, 390, 330, 320],
|
||||
},
|
||||
{
|
||||
name: "Search Engine",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-carousel__item h3 {
|
||||
display: flex;
|
||||
color: #475669;
|
||||
opacity: 0.75;
|
||||
line-height: 300px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
104
frontEnd/src/pages/publicPages/user/userView.vue
Normal file
104
frontEnd/src/pages/publicPages/user/userView.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<el-descriptions
|
||||
title="个人信息"
|
||||
style="padding: 15px"
|
||||
border
|
||||
size="large"
|
||||
:column="2"
|
||||
v-loading="loading"
|
||||
element-loading-text="正在初始化数据...">
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon>
|
||||
<User />
|
||||
</el-icon>
|
||||
姓名 </template
|
||||
>{{ user.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon>
|
||||
<Female v-if="user.sex === 0 || user.sex === '女'" />
|
||||
<Male v-if="user.sex === 1 || user.sex === '男'" />
|
||||
</el-icon>
|
||||
性别 </template
|
||||
>{{ user.sex }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon>
|
||||
<Iphone />
|
||||
</el-icon>
|
||||
电话 </template
|
||||
>{{ user.phone }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon> <Avatar /> </el-icon>状态
|
||||
</template>
|
||||
<el-tag type="success" v-if="user.userState || user.userState === 1"
|
||||
>正常</el-tag
|
||||
>
|
||||
<el-tag type="danger" v-if="!user.userState || user.userState === 0"
|
||||
>未启用</el-tag
|
||||
>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon> <UserFilled /> </el-icon>角色
|
||||
</template>
|
||||
<el-tag>
|
||||
{{
|
||||
roles.find((item) => Number(item.id) === Number(user.role))?.name ||
|
||||
"无"
|
||||
}}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon> <TakeawayBox /> </el-icon>生日 </template
|
||||
>{{ dayjs(user.birthday).format("YYYYH-MM-DD") }}</el-descriptions-item
|
||||
>
|
||||
<!-- <el-descriptions-item label="年龄">{{ user.age }}</el-descriptions-item> -->
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon> <OfficeBuilding /> </el-icon>所在省市区
|
||||
</template>
|
||||
{{ user.province + "/" + user.city + "/" + user.area }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<el-icon><LocationInformation /></el-icon>详细地址
|
||||
</template>
|
||||
{{ user.address }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { userType } from "@/types/user";
|
||||
import dayjs from "dayjs";
|
||||
import { roleDataList } from "@/lib/api/publicApiList";
|
||||
import { roleType } from "@/types/role";
|
||||
const props = defineProps<{
|
||||
data: userType;
|
||||
}>();
|
||||
const user = props.data;
|
||||
let roles = ref<roleType[]>([]);
|
||||
let loading = ref(true);
|
||||
|
||||
onMounted(async () => {
|
||||
roles.value = await roleDataList();
|
||||
loading.value = false;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-descriptions__label) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-icon {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
inline
|
||||
style="padding-bottom: 20px">
|
||||
<el-form-item label="服务分类名称">
|
||||
<el-input
|
||||
v-model="formData.name"
|
||||
placeholder="请输入服务分类名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注"></el-input>
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-form-item label="分类" style="width: 100%">
|
||||
<el-tree-select
|
||||
check-strictly
|
||||
:check-on-click-node="true"
|
||||
v-model="formData.parentId"
|
||||
:props="{ label: 'name', value: 'id' }"
|
||||
:data="categoryOptions"
|
||||
:render-after-expand="false"
|
||||
style="width: 240px" />
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import api from "@/lib/request";
|
||||
|
||||
// 表单数据
|
||||
const formData = defineModel({
|
||||
default: {
|
||||
name: "", // 服务项目名称
|
||||
remark: "", // 备注
|
||||
parentId: 0, // 分类ID
|
||||
},
|
||||
});
|
||||
|
||||
// 分类选项数据
|
||||
const categoryOptions = ref<{ id: number; name: string }[]>([]);
|
||||
|
||||
// 获取分类树并转换为下拉框选项
|
||||
const loadCategoryTree = async () => {
|
||||
try {
|
||||
const res = await api().get("/service-category/list");
|
||||
if (res.data.list.length) {
|
||||
categoryOptions.value = [{ id: 0, name: "无" }, ...res.data.list];
|
||||
} else {
|
||||
categoryOptions.value = [{ id: 0, name: "无" }];
|
||||
}
|
||||
} catch (err) {
|
||||
ElMessage.error("获取分类树失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时获取分类树
|
||||
onMounted(() => {
|
||||
loadCategoryTree();
|
||||
});
|
||||
</script>
|
||||
20
frontEnd/src/pages/serviceList/serviceCategory/page/view.vue
Normal file
20
frontEnd/src/pages/serviceList/serviceCategory/page/view.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<el-descriptions title="服务项目详情" border style="margin-bottom: 30px">
|
||||
<el-descriptions-item label="服务项目名称">{{
|
||||
data.name
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="数量">{{
|
||||
data.quantity
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="单位">{{ data.unit }}</el-descriptions-item>
|
||||
<el-descriptions-item label="售价">{{ data.price }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ data.remark }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分类">{{
|
||||
data.category
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const data = defineModel<ServiceItemType>({ required: true });
|
||||
</script>
|
||||
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div>
|
||||
<baseTableHeader
|
||||
title="服务分类"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" :inline="true" label-position="right">
|
||||
<el-form-item label="分类名称:">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入分类名称"></el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="分类:">
|
||||
<el-input
|
||||
v-model="searchForm.category"
|
||||
placeholder="请输入分类"></el-input>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button type="primary" @click="add" size="small"
|
||||
><el-icon> <CirclePlus /> </el-icon>新增</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
style="width: 100%"
|
||||
:tree-props="{ children: 'children' }"
|
||||
row-key="id"
|
||||
:indent="30"
|
||||
:showPagination="false"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim">
|
||||
<template #colunm>
|
||||
<el-table-column prop="name" label="服务分类名称" />
|
||||
<el-table-column prop="remark" label="备注" align="center" />
|
||||
<el-table-column
|
||||
#default="{ row }"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right"
|
||||
width="250">
|
||||
<!-- <el-button size="small" type="primary" @click="examine(row)"
|
||||
>查看</el-button
|
||||
> -->
|
||||
<el-button size="small" type="warning" @click="update(row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="deleteData(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="50%"
|
||||
:before-close="handleDialogClose"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<addOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
v-model="currentServiceItem"
|
||||
v-if="
|
||||
pageVisibleState.showPageType.edit ||
|
||||
pageVisibleState.showPageType.add
|
||||
"></addOrEdit>
|
||||
<serviceItemView
|
||||
v-if="pageVisibleState.showPageType.view"
|
||||
v-model="currentServiceItem"></serviceItemView>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted, ref, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import addOrEdit from "./page/addOrEdit.vue";
|
||||
import serviceItemView from "./page/view.vue";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "新增服务项目",
|
||||
edit: "服务项目编辑",
|
||||
view: "服务项目查看",
|
||||
});
|
||||
const searchForm = reactive({
|
||||
name: "",
|
||||
category: 0,
|
||||
});
|
||||
|
||||
let currentServiceItem = ref<ServiceItemType>({
|
||||
name: "",
|
||||
remark: "",
|
||||
parentId: 0,
|
||||
});
|
||||
|
||||
watch(
|
||||
() => pageVisibleState.show2LevelPage,
|
||||
(newVal) => {
|
||||
if (newVal.value === false) {
|
||||
resetServiceItem();
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/service-category/list",
|
||||
searchUrl: "/service-category/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
function add() {
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
|
||||
function examine(row: ServiceItemType) {
|
||||
currentServiceItem.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.view = true;
|
||||
}
|
||||
function update(row: ServiceItemType) {
|
||||
currentServiceItem.value = { ...row };
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.edit = true;
|
||||
}
|
||||
async function deleteData(row: ServiceItemType) {
|
||||
await ElMessageBox.confirm("确定要删除该服务分类吗?", {
|
||||
type: "error",
|
||||
});
|
||||
let respone = await api().get("/service-category/delete?id=" + row.id);
|
||||
if (respone.code === 200) {
|
||||
ElMessage.success("服务项目删除成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
}
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("list");
|
||||
ElMessage.success("重置成功!");
|
||||
}
|
||||
|
||||
function handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
}
|
||||
async function addConfim() {
|
||||
await ElMessageBox.confirm("确定新增该分类吗?", "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
let res = await api().post("/service-category/add", currentServiceItem.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("添加成功");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
}
|
||||
|
||||
async function editConfim() {
|
||||
ElMessageBox.confirm("确认修改该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
let respone = await api().post(
|
||||
"/service-category/update",
|
||||
currentServiceItem.value
|
||||
);
|
||||
if (respone.code == 200) {
|
||||
ElMessage.success("修改成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetServiceItem() {
|
||||
currentServiceItem.value = {
|
||||
name: "",
|
||||
quantity: 0,
|
||||
category: 0,
|
||||
unit: "",
|
||||
price: 0,
|
||||
remark: "",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<el-form
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
inline
|
||||
style="padding-bottom: 20px">
|
||||
<el-form-item label="服务项目名称">
|
||||
<el-input
|
||||
v-model="formData.name"
|
||||
placeholder="请输入服务项目名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="单位">
|
||||
<el-input v-model="formData.unit" placeholder="请输入单位"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="售价">
|
||||
<el-input v-model="formData.price" placeholder="请输入售价"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" v-if="props.type === '手工录入服务'">
|
||||
<el-input v-model="formData.quantity" placeholder="请输入数量"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注"></el-input>
|
||||
</el-form-item>
|
||||
<el-row v-if="props.type !== '手工录入服务'">
|
||||
<el-form-item label="分类" style="width: 100%">
|
||||
<serviceSelect v-model="formData.parentId"></serviceSelect>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import api from "@/lib/request";
|
||||
|
||||
let props = defineProps<{
|
||||
type: "手工录入服务";
|
||||
}>();
|
||||
// 表单数据
|
||||
const formData = defineModel({
|
||||
default: {
|
||||
name: "", // 服务项目名称
|
||||
quantity: 1, // 数量
|
||||
unit: "", // 单位
|
||||
price: 0, // 售价
|
||||
remark: "", // 备注
|
||||
parentId: 0, // 分类ID
|
||||
},
|
||||
});
|
||||
|
||||
// 分类选项数据
|
||||
const categoryOptions = ref<{ id: number; name: string }[]>([]);
|
||||
|
||||
// 页面加载时获取分类树
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
20
frontEnd/src/pages/serviceList/serviceItem/page/view.vue
Normal file
20
frontEnd/src/pages/serviceList/serviceItem/page/view.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<el-descriptions title="服务项目详情" border style="margin-bottom: 30px">
|
||||
<el-descriptions-item label="服务项目名称">{{
|
||||
data.name
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="数量">{{
|
||||
data.quantity
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="单位">{{ data.unit }}</el-descriptions-item>
|
||||
<el-descriptions-item label="售价">{{ data.price }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注">{{ data.remark }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分类">{{
|
||||
data.category
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const data = defineModel<ServiceItemType>({ required: true });
|
||||
</script>
|
||||
247
frontEnd/src/pages/serviceList/serviceItem/serviceItemList.vue
Normal file
247
frontEnd/src/pages/serviceList/serviceItem/serviceItemList.vue
Normal file
@@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<div>
|
||||
<baseTableHeader
|
||||
title="服务项目"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" :inline="true" label-position="right">
|
||||
<el-form-item label="服务项目名称:">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入服务项目名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类:">
|
||||
<serviceSelect v-model="searchForm.category"></serviceSelect>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button type="primary" @click="add" size="small"
|
||||
><el-icon> <CirclePlus /> </el-icon>新增</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
style="width: 100%"
|
||||
border
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim">
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="80"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column prop="name" label="服务项目名称" align="center" />
|
||||
<!-- <el-table-column
|
||||
prop="quantity"
|
||||
label="数量"
|
||||
align="center"
|
||||
width="80" /> -->
|
||||
<el-table-column prop="unit" label="单位" align="center" width="80" />
|
||||
<el-table-column
|
||||
prop="price"
|
||||
label="售价"
|
||||
align="center"
|
||||
width="120" />
|
||||
<el-table-column prop="remark" label="备注" align="center" />
|
||||
<el-table-column prop="parentId" label="分类" align="center">
|
||||
<template #default="{ row }">
|
||||
{{
|
||||
serviceCaregoryOptions.find((item) => item.id === row.parentId)
|
||||
?.name
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
#default="{ row }"
|
||||
label="操作"
|
||||
align="center"
|
||||
fixed="right"
|
||||
width="250">
|
||||
<el-button size="small" type="primary" @click="examine(row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button size="small" type="warning" @click="update(row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="deleteData(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="50%"
|
||||
:before-close="handleDialogClose"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<addOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
v-model="currentServiceItem"
|
||||
v-if="
|
||||
pageVisibleState.showPageType.edit ||
|
||||
pageVisibleState.showPageType.add
|
||||
"></addOrEdit>
|
||||
<serviceItemView
|
||||
v-if="pageVisibleState.showPageType.view"
|
||||
v-model="currentServiceItem"></serviceItemView>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted, ref, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import addOrEdit from "./page/addOrEdit.vue";
|
||||
import serviceItemView from "./page/view.vue";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import serviceSelect from "@/components/serviceSelect/serviceSelect.vue";
|
||||
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "新增服务项目",
|
||||
edit: "服务项目编辑",
|
||||
view: "服务项目查看",
|
||||
});
|
||||
const searchForm = reactive({
|
||||
name: "",
|
||||
category: 0,
|
||||
});
|
||||
|
||||
let currentServiceItem = ref<ServiceItemType>({
|
||||
name: "",
|
||||
quantity: 0,
|
||||
category: 0,
|
||||
unit: "",
|
||||
price: 0,
|
||||
remark: "",
|
||||
});
|
||||
|
||||
const serviceCaregoryOptions = ref<{ id: number; name: string }[]>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
const res = await api().get("/service-category/list");
|
||||
|
||||
serviceCaregoryOptions.value = [{ id: 0, name: "无" }, ...res.data.list];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => pageVisibleState.show2LevelPage,
|
||||
(newVal) => {
|
||||
if (newVal.value === false) {
|
||||
resetServiceItem();
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/service-item/list",
|
||||
searchUrl: "/service-item/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
function add() {
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
|
||||
function examine(row: ServiceItemType) {
|
||||
currentServiceItem.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.view = true;
|
||||
}
|
||||
function update(row: ServiceItemType) {
|
||||
currentServiceItem.value = { ...row };
|
||||
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.edit = true;
|
||||
}
|
||||
async function deleteData(row: ServiceItemType) {
|
||||
await ElMessageBox.confirm("确定要删除该服务项目吗?", {
|
||||
type: "error",
|
||||
});
|
||||
let respone = await api().get("/service-item/delete?id=" + row.id);
|
||||
if (respone.code === 200) {
|
||||
ElMessage.success("服务项目删除成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
}
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("list");
|
||||
ElMessage.success("重置成功!");
|
||||
}
|
||||
|
||||
function handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
}
|
||||
async function addConfim() {
|
||||
await ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
});
|
||||
let res = await api().post("/service-item/add", currentServiceItem.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("添加成功");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
}
|
||||
|
||||
async function editConfim() {
|
||||
ElMessageBox.confirm("确认修改该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
let respone = await api().post(
|
||||
"/service-item/update",
|
||||
currentServiceItem.value
|
||||
);
|
||||
if (respone.code == 200) {
|
||||
ElMessage.success("修改成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetServiceItem() {
|
||||
currentServiceItem.value = {
|
||||
name: "",
|
||||
quantity: 0,
|
||||
category: 0,
|
||||
unit: "",
|
||||
price: 0,
|
||||
remark: "",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
20
frontEnd/src/pages/serviceList/serviceList.vue
Normal file
20
frontEnd/src/pages/serviceList/serviceList.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane>
|
||||
<template #label>服务项目</template>
|
||||
<serviceItemList></serviceItemList>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane>
|
||||
<template #label> 服务分类 </template>
|
||||
<serviceCategory> </serviceCategory>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import serviceItemList from "./serviceItem/serviceItemList.vue";
|
||||
import serviceCategory from "./serviceCategory/serviceCategory.vue";
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
713
frontEnd/src/pages/statistics/dayIncome/dayIncome.vue
Normal file
713
frontEnd/src/pages/statistics/dayIncome/dayIncome.vue
Normal file
@@ -0,0 +1,713 @@
|
||||
<template>
|
||||
<div style="background-color: #fff; padding: 15px">
|
||||
<baseTableHeader
|
||||
title="公司日收入统计"
|
||||
@resetSearch="reset"
|
||||
@search="query">
|
||||
<template #content>
|
||||
<el-form v-model="searchForm">
|
||||
<el-row :gutter="15">
|
||||
<el-col>
|
||||
<el-form-item label="购买日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.purchaseDate"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择日期"
|
||||
end-placeholder="选择日期"
|
||||
@change="dataChange" />
|
||||
</el-form-item>
|
||||
<!-- <div>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="margin-left: 15px"
|
||||
@click="query"
|
||||
>查询</el-button
|
||||
><el-button
|
||||
type="warning"
|
||||
style="margin-left: 15px"
|
||||
@click="reset"
|
||||
>重置</el-button
|
||||
>
|
||||
<el-button v-print="print">打印单据</el-button>
|
||||
</div> -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button v-print="print"
|
||||
><img
|
||||
src="/assets/icon/打印机.svg"
|
||||
style="margin-right: 5px"
|
||||
width="20"
|
||||
height="20" />打印单据</el-button
|
||||
>
|
||||
<el-button @click="exportFile"
|
||||
><img
|
||||
src="/assets/images/Excel.svg"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20" />导出</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
|
||||
<div id="print-container">
|
||||
<h2
|
||||
style="
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-size: 20pt;
|
||||
padding: 15px;
|
||||
font-weight: bold;
|
||||
">
|
||||
殡仪服务公司日收入统计表
|
||||
</h2>
|
||||
<table
|
||||
id="print-table"
|
||||
class=""
|
||||
style="
|
||||
font-family: 仿宋;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
colspan="4"
|
||||
class="l"
|
||||
style="
|
||||
text-align: left;
|
||||
|
||||
font-weight: bold;
|
||||
font-size: 25px;
|
||||
font-family: 宋体;
|
||||
">
|
||||
<span>
|
||||
统计时间:{{
|
||||
dayjs(searchForm.startDate).format("YYYY-MM-DD HH:mm:ss")
|
||||
}}
|
||||
至
|
||||
{{ dayjs(searchForm.endDate).format("YYYY-MM-DD HH:mm:ss") }}
|
||||
</span>
|
||||
<!-- <span v-else>
|
||||
开始时间:{{ dayjs(searchForm.startDate).format("YYYY-MM-DD") }}
|
||||
</span> -->
|
||||
</td>
|
||||
<td
|
||||
colspan="2"
|
||||
class="l"
|
||||
style="
|
||||
text-align: left;
|
||||
|
||||
font-weight: bold;
|
||||
font-size: 25px;
|
||||
font-family: 宋体;
|
||||
">
|
||||
单位:元
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b></b>
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>小计</b>
|
||||
</td>
|
||||
<td
|
||||
colspan="2"
|
||||
style="height: 30px; border: 1px solid black; text-align: center">
|
||||
<b>总计</b>
|
||||
</td>
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>备注</b>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
现金
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.service.cashAmount + statsData.retail.cashAmount }}
|
||||
</td>
|
||||
<td
|
||||
rowspan="6"
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{
|
||||
statsData.service.cashAmount +
|
||||
statsData.service.unionPayAmount +
|
||||
statsData.service.cardAmount +
|
||||
statsData.service.publicTransferAmount +
|
||||
statsData.service.workshopPayment +
|
||||
statsData.retail.cashAmount +
|
||||
statsData.retail.unionPayAmount +
|
||||
statsData.retail.cardAmount +
|
||||
statsData.retail.publicTransferAmount +
|
||||
statsData.retail.workshopPayment
|
||||
}}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
银联
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{
|
||||
statsData.service.unionPayAmount +
|
||||
statsData.retail.unionPayAmount
|
||||
}}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
银行卡
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.service.cardAmount + statsData.retail.cardAmount }}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
车间支付
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{
|
||||
statsData.service.workshopPayment +
|
||||
statsData.retail.workshopPayment
|
||||
}}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
对公转账
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{
|
||||
statsData.service.publicTransferAmount +
|
||||
statsData.retail.publicTransferAmount
|
||||
}}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>现金合计</b>
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>微信合计</b>
|
||||
</td>
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>银行卡合计</b>
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>车间支付合计</b>
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>对公转账合计</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.total.cashAmount }}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.total.unionPayAmount }}
|
||||
</td>
|
||||
|
||||
<td
|
||||
colspan="2"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.total.cardAmount }}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.total.workshopPayment }}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{ statsData.total.publicTransferAmount }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
<b>总合计:</b>
|
||||
</td>
|
||||
<td
|
||||
colspan="5"
|
||||
style="
|
||||
height: 30px;
|
||||
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
">
|
||||
{{
|
||||
statsData.total.cashAmount +
|
||||
statsData.total.unionPayAmount +
|
||||
statsData.total.cardAmount +
|
||||
statsData.total.workshopPayment +
|
||||
statsData.total.publicTransferAmount
|
||||
}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, ref } from "vue";
|
||||
import request from "@/lib/request";
|
||||
import dayjs from "dayjs";
|
||||
import ExcelJS from "exceljs";
|
||||
|
||||
export type PaymentStats = {
|
||||
cashAmount: number;
|
||||
unionPayAmount: number;
|
||||
cardAmount: number;
|
||||
publicTransferAmount: number;
|
||||
workshopPayment: number;
|
||||
};
|
||||
|
||||
// 完整响应类型
|
||||
export type StatsResponse = {
|
||||
retail: PaymentStats;
|
||||
service: PaymentStats;
|
||||
total: PaymentStats;
|
||||
};
|
||||
|
||||
let searchForm = ref({
|
||||
startDate: dayjs().startOf("day").toDate(),
|
||||
endDate: new Date(),
|
||||
purchaseDate: [dayjs().startOf("day").toDate(), new Date()],
|
||||
});
|
||||
|
||||
let statsData = ref<StatsResponse>({
|
||||
retail: {
|
||||
cashAmount: 0,
|
||||
unionPayAmount: 0,
|
||||
cardAmount: 0,
|
||||
publicTransferAmount: 0,
|
||||
workshopPayment: 0,
|
||||
},
|
||||
service: {
|
||||
cashAmount: 0,
|
||||
unionPayAmount: 0,
|
||||
cardAmount: 0,
|
||||
publicTransferAmount: 0,
|
||||
workshopPayment: 0,
|
||||
},
|
||||
total: {
|
||||
cashAmount: 0,
|
||||
unionPayAmount: 0,
|
||||
cardAmount: 0,
|
||||
publicTransferAmount: 0,
|
||||
workshopPayment: 0,
|
||||
},
|
||||
});
|
||||
let searched = ref(false);
|
||||
|
||||
request()
|
||||
.get("/stats/dayIncome", {
|
||||
params: {
|
||||
startDate: dayjs().startOf("day").toDate(),
|
||||
endDate: new Date(),
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
statsData.value = res.data;
|
||||
});
|
||||
|
||||
const print = {
|
||||
id: "print-container",
|
||||
};
|
||||
|
||||
function query() {
|
||||
searched.value = false;
|
||||
request()
|
||||
.get("/stats/dayIncome", {
|
||||
params: {
|
||||
startDate: dayjs(searchForm.value.startDate).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
),
|
||||
endDate: dayjs(searchForm.value.endDate).format("YYYY-MM-DD HH:mm:ss"),
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
statsData.value = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
searchForm.value = {
|
||||
startDate: dayjs().startOf("day").toDate(),
|
||||
endDate: new Date(),
|
||||
purchaseDate: [dayjs().startOf("day").toDate(), new Date()],
|
||||
};
|
||||
query();
|
||||
}
|
||||
|
||||
function dataChange(val: Date[]) {
|
||||
searchForm.value.startDate = val[0];
|
||||
searchForm.value.endDate = val[1];
|
||||
}
|
||||
|
||||
async function exportFile() {
|
||||
try {
|
||||
// 获取模板文件
|
||||
const response = await fetch("/excelTemple/日收入统计.xlsx");
|
||||
const buffer = await response.arrayBuffer();
|
||||
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(buffer);
|
||||
const sheet = workbook.getWorksheet(1); // 默认第一个工作表
|
||||
|
||||
const startDate = dayjs(searchForm.value.startDate).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
);
|
||||
const endDate = dayjs(searchForm.value.endDate).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
);
|
||||
|
||||
// 工具函数:填充值并保留样式
|
||||
const setCellValueWithStyle = (cellAddress, value) => {
|
||||
const cell = sheet.getCell(cellAddress);
|
||||
const style = { ...cell.style };
|
||||
cell.value = value;
|
||||
cell.style = style;
|
||||
};
|
||||
|
||||
// 填充各项内容(保持样式)
|
||||
setCellValueWithStyle("C2", `${startDate} 至 ${endDate}`);
|
||||
|
||||
setCellValueWithStyle("B4", statsData.value.total.cashAmount);
|
||||
|
||||
setCellValueWithStyle("B5", statsData.value.total.unionPayAmount);
|
||||
setCellValueWithStyle("B6", statsData.value.total.cardAmount);
|
||||
setCellValueWithStyle("B7", statsData.value.total.workshopPayment);
|
||||
setCellValueWithStyle("B8", statsData.value.total.publicTransferAmount);
|
||||
|
||||
const total =
|
||||
statsData.value.service.cashAmount +
|
||||
statsData.value.service.unionPayAmount +
|
||||
statsData.value.service.cardAmount +
|
||||
statsData.value.service.publicTransferAmount +
|
||||
statsData.value.service.workshopPayment +
|
||||
statsData.value.retail.cashAmount +
|
||||
statsData.value.retail.unionPayAmount +
|
||||
statsData.value.retail.cardAmount +
|
||||
statsData.value.retail.publicTransferAmount +
|
||||
statsData.value.retail.workshopPayment;
|
||||
setCellValueWithStyle("C4", total);
|
||||
|
||||
setCellValueWithStyle("A11", statsData.value.total.cashAmount);
|
||||
setCellValueWithStyle("B11", statsData.value.total.unionPayAmount);
|
||||
setCellValueWithStyle("C11", statsData.value.total.cardAmount);
|
||||
setCellValueWithStyle("D11", statsData.value.total.workshopPayment);
|
||||
setCellValueWithStyle("E11", statsData.value.total.publicTransferAmount);
|
||||
|
||||
const grandTotal =
|
||||
statsData.value.total.cashAmount +
|
||||
statsData.value.total.unionPayAmount +
|
||||
statsData.value.total.cardAmount +
|
||||
statsData.value.total.workshopPayment +
|
||||
statsData.value.total.publicTransferAmount;
|
||||
setCellValueWithStyle("B12", grandTotal);
|
||||
|
||||
// 导出文件
|
||||
const newBuffer = await workbook.xlsx.writeBuffer();
|
||||
const blob = new Blob([newBuffer], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "日收入统计.xlsx";
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error("导出 Excel 文件时出错:", error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
tr,
|
||||
td {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
#print-container {
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 5mm !important;
|
||||
font-size: 14pt;
|
||||
color: #000 !important;
|
||||
font-family: Microsoft YaHei, "SimSun", serif !important;
|
||||
|
||||
/* 添加表格布局优化 */
|
||||
table {
|
||||
width: 100% !important;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse !important;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 5px 2mm !important;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
/* 重置body和html的布局方式 */
|
||||
body,
|
||||
html {
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 15pt;
|
||||
}
|
||||
|
||||
#print-container {
|
||||
min-height: 297mm; /* A4纸高度 */
|
||||
width: 100% !important;
|
||||
vertical-align: top !important;
|
||||
position: relative;
|
||||
top: 0;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* 隐藏不需要打印的元素 */
|
||||
.el-form,
|
||||
.el-button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<div>引导员销售统计</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
<style lang="scss" scoped></style>
|
||||
452
frontEnd/src/pages/statistics/saleDetail/saleDetail.vue
Normal file
452
frontEnd/src/pages/statistics/saleDetail/saleDetail.vue
Normal file
@@ -0,0 +1,452 @@
|
||||
<template>
|
||||
<div style="background-color: #fff; padding: 15px">
|
||||
<baseTableHeader title="公司销售明细" @resetSearch="reset" @search="query">
|
||||
<template #content>
|
||||
<el-form v-model="searchForm" label-width="100">
|
||||
<el-row :gutter="25">
|
||||
<el-col :span="10">
|
||||
<el-form-item label="统计日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.dateRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择开始日期"
|
||||
end-placeholder="选择结束日期"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
@change="dateChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="逝者姓名">
|
||||
<el-input
|
||||
v-model="searchForm.deceasedName"
|
||||
placeholder="输入逝者名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="购买人">
|
||||
<el-input
|
||||
v-model="searchForm.familyName"
|
||||
placeholder="输入购买人" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="服务名称">
|
||||
<el-input
|
||||
v-model="searchForm.serviceName"
|
||||
placeholder="输入服务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6" label="引导员">
|
||||
<el-form-item label="引导员">
|
||||
<guideList v-model="searchForm.guide"></guideList>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button @click="exportSalesDetailsExcel('当前')"
|
||||
><img
|
||||
src="/assets/images/Excel.svg"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20" />导出当前</el-button
|
||||
>
|
||||
<el-button @click="exportSalesDetailsExcel('所有')"
|
||||
><img
|
||||
src="/assets/images/Excel.svg"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20" />导出所有</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
type="index"
|
||||
width="80"
|
||||
fixed="left"
|
||||
label="序号"
|
||||
align="center"></el-table-column>
|
||||
<el-table-column
|
||||
width="120"
|
||||
fixed="left"
|
||||
prop="deceasedRetail.checkoutDate"
|
||||
label="结账日期"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.deceasedRetail.checkoutDate.split(" ")[0] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="逝者姓名"
|
||||
width="120"
|
||||
fixed="left"
|
||||
align="center">
|
||||
<template #default="{ row }">
|
||||
<span>{{
|
||||
row.deceased.name ||
|
||||
row.deceased.familyName ||
|
||||
row.deceasedRetail.deceasedName
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceasedRetail.guide"
|
||||
label="引导员"
|
||||
fixed="left"
|
||||
align="center" />
|
||||
<el-table-column prop="deceased.gender" label="性别" align="center" />
|
||||
<el-table-column prop="deceased.age" label="年龄" align="center" />
|
||||
<el-table-column
|
||||
prop="deceased.idNumber"
|
||||
label="身份证"
|
||||
align="center"
|
||||
width="180" />
|
||||
<el-table-column label="地址" align="center" width="280">
|
||||
<template #default="{ row }">
|
||||
<div style="text-align: left">
|
||||
<span
|
||||
v-if="row.deceased.province || row.deceasedRetail.province"
|
||||
>{{
|
||||
row.deceased.province || row.deceasedRetail.province
|
||||
}}/</span
|
||||
>
|
||||
<span v-if="row.deceased.city || row.deceasedRetail.city"
|
||||
>{{ row.deceased.city || row.deceasedRetail.city }}/</span
|
||||
>
|
||||
<span
|
||||
v-if="row.deceased.address || row.deceasedRetail.address"
|
||||
>{{
|
||||
row.deceased.address || row.deceasedRetail.address
|
||||
}}</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.name"
|
||||
label="购买人姓名"
|
||||
align="center"
|
||||
width="120">
|
||||
<template #default="{ row }">
|
||||
<span>{{
|
||||
row.deceased.familyName || row.deceasedRetail.deceasedName
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="deceased.familyPhone"
|
||||
label="购买人电话"
|
||||
align="center"
|
||||
width="150" />
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="项目名称"
|
||||
align="center"
|
||||
width="150" />
|
||||
<el-table-column
|
||||
prop="price"
|
||||
label="单价"
|
||||
align="center"
|
||||
width="150" />
|
||||
<el-table-column
|
||||
prop="quantity"
|
||||
label="数量"
|
||||
align="center"
|
||||
width="150" />
|
||||
<el-table-column prop="sum" label="金额" align="center" width="150">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="remark"
|
||||
label="备注"
|
||||
width="280"
|
||||
align="center" />
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import request from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { nextTick, onMounted, ref } from "vue";
|
||||
import ExcelJS from "exceljs";
|
||||
|
||||
const categories = ref<Array<{ id: number; name: string }>>([]);
|
||||
let searchForm = ref({
|
||||
dateRange: [],
|
||||
serviceName: "",
|
||||
categoryName: "",
|
||||
categories: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
deceasedName: "",
|
||||
guide: "",
|
||||
familyName: "",
|
||||
});
|
||||
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/stats/salesDetails",
|
||||
searchUrl: "/stats/salesDetails",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
let table = ref();
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
const res = await request().get("/public/service-categories");
|
||||
categories.value = res.data.map((item: any) => ({
|
||||
id: item.value,
|
||||
name: item.label,
|
||||
}));
|
||||
} catch (error) {
|
||||
ElMessage.error("分类加载失败");
|
||||
}
|
||||
};
|
||||
const getSummaries = (param: { columns: any[]; data: any[] }) => {
|
||||
const { columns, data } = param;
|
||||
const sums: any[] = [];
|
||||
// 需要统计的字段列表
|
||||
const sumKeys = ["price", "quantity", "sum"];
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = "合计";
|
||||
return;
|
||||
}
|
||||
if (sumKeys.includes(column.property)) {
|
||||
const values = data.map((item) => {
|
||||
const keys = column.property.split(".");
|
||||
let value = item;
|
||||
for (const key of keys) {
|
||||
value = value?.[key] || 0;
|
||||
}
|
||||
return Number(value) || 0;
|
||||
});
|
||||
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
const sum = values.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
sums[index] = `${sum.toFixed(2)}`;
|
||||
} else {
|
||||
sums[index] = "0.00 元";
|
||||
}
|
||||
} else {
|
||||
sums[index] = "";
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
};
|
||||
|
||||
const dateChange = (val: string[]) => {
|
||||
if (val?.length === 2) {
|
||||
searchForm.value.dateRange = val;
|
||||
searchForm.value.startDate = val[0];
|
||||
searchForm.value.endDate = val[1];
|
||||
}
|
||||
};
|
||||
|
||||
function reset() {
|
||||
searchForm.value = {
|
||||
dateRange: [],
|
||||
serviceName: "",
|
||||
categoryName: "",
|
||||
categories: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
deceasedName: "",
|
||||
familyName: "",
|
||||
};
|
||||
table.value.methods.setDataType("reset");
|
||||
}
|
||||
|
||||
function query() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchCategories();
|
||||
});
|
||||
|
||||
async function exportSalesDetailsExcel(type: "当前" | "所有") {
|
||||
try {
|
||||
let list = [];
|
||||
|
||||
if (type === "当前") {
|
||||
list = table.value.tableData.data;
|
||||
} else {
|
||||
// 1. 获取所有数据
|
||||
const res = await request().post("/stats/salesDetails", {
|
||||
pageSize: 999999999,
|
||||
pageNumber: 1,
|
||||
dateRange: [],
|
||||
serviceName: "",
|
||||
categoryName: "",
|
||||
categories: "",
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
deceasedName: "",
|
||||
guide: "",
|
||||
familyName: "",
|
||||
});
|
||||
list = res.data?.list;
|
||||
}
|
||||
|
||||
// 2. 获取模板文件
|
||||
const templateRes = await fetch("/excelTemple/销售明细.xlsx");
|
||||
const buffer = await templateRes.arrayBuffer();
|
||||
|
||||
// 3. 加载 Excel 模板
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(buffer);
|
||||
const sheet = workbook.getWorksheet(1); // 默认取第一个 sheet
|
||||
|
||||
// 4. 从第 3 行开始填充数据
|
||||
list.forEach((item, index) => {
|
||||
const row = sheet.getRow(index + 2); // 第3行开始
|
||||
const deceased = item.deceased || {};
|
||||
const retail = item.deceasedRetail || {};
|
||||
|
||||
row.getCell(1).value = index + 1;
|
||||
row.getCell(2).value = retail.checkoutDate || "";
|
||||
row.getCell(3).value = deceased.name || "";
|
||||
row.getCell(4).value = retail.guide || "";
|
||||
row.getCell(5).value = deceased.gender || "";
|
||||
row.getCell(6).value = deceased.age || "";
|
||||
row.getCell(7).value = deceased.idNumber || "";
|
||||
row.getCell(8).value = deceased.address || "";
|
||||
row.getCell(9).value = deceased.familyName || "";
|
||||
row.getCell(10).value = deceased.familyPhone || "";
|
||||
row.getCell(11).value = item.name || "";
|
||||
row.getCell(12).value = item.price || "";
|
||||
row.getCell(13).value = item.quantity || "";
|
||||
row.getCell(14).value = item.sum || "";
|
||||
row.getCell(15).value = item.remark || "";
|
||||
row.eachCell((cell) => {
|
||||
cell.alignment = { vertical: "middle", horizontal: "center" };
|
||||
});
|
||||
row.commit(); // 应用修改
|
||||
});
|
||||
|
||||
// 5. 导出为 blob
|
||||
const blob = await workbook.xlsx.writeBuffer();
|
||||
const file = new Blob([blob], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
// 6. 触发下载
|
||||
const url = URL.createObjectURL(file);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "销售明细.xlsx";
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error("导出销售明细失败:", error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.loading-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.is-loading {
|
||||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #000;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
text-align: center !important;
|
||||
}
|
||||
@media print {
|
||||
/* 移除全局布局影响 */
|
||||
body,
|
||||
html {
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
margin: 2mm !important; /* 添加安全边距 */
|
||||
}
|
||||
|
||||
#print-container {
|
||||
width: auto !important; /* 改为自动宽度 */
|
||||
margin: 0 auto !important; /* 居中显示 */
|
||||
font-size: 12pt !important; /* 调整字号 */
|
||||
min-height: 297mm;
|
||||
}
|
||||
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* 优化单元格内边距 */
|
||||
td,
|
||||
th {
|
||||
padding: 4px 2mm !important;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
}
|
||||
|
||||
tr,
|
||||
td {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
#print-container {
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 5mm !important;
|
||||
font-size: 14pt;
|
||||
color: #000 !important;
|
||||
font-family: Microsoft YaHei, "SimSun", serif !important;
|
||||
}
|
||||
/* 添加表格布局优化 */
|
||||
table {
|
||||
width: 100% !important;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse !important;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 10px 2mm !important;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
498
frontEnd/src/pages/statistics/sales/sales.vue
Normal file
498
frontEnd/src/pages/statistics/sales/sales.vue
Normal file
@@ -0,0 +1,498 @@
|
||||
<template>
|
||||
<div style="background-color: #fff; padding: 15px">
|
||||
<baseTableHeader title="销售统计报表" @resetSearch="reset" @search="query">
|
||||
<template #content>
|
||||
<el-form v-model="searchForm">
|
||||
<el-row :gutter="25">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="统计日期">
|
||||
<el-date-picker
|
||||
v-model="searchForm.dateRange"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="选择开始日期"
|
||||
end-placeholder="选择结束日期"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
@change="dateChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="服务名称">
|
||||
<el-input
|
||||
v-model="searchForm.serviceName"
|
||||
placeholder="输入服务名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="项目分类">
|
||||
<el-select
|
||||
v-model="searchForm.categoryName"
|
||||
placeholder="选择分类"
|
||||
clearable>
|
||||
<el-option
|
||||
v-for="category in categories"
|
||||
:key="category.id"
|
||||
:label="category.name"
|
||||
:value="category.name" />
|
||||
<el-option label="其他服务" value="其他服务" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <div>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="margin-left: 15px"
|
||||
@click="query"
|
||||
:loading="loading">
|
||||
查询
|
||||
</el-button>
|
||||
<el-button type="warning" @click="reset">重置</el-button>
|
||||
</div> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button size="small" v-print="print"
|
||||
><img
|
||||
src="/assets/icon/打印机.svg"
|
||||
style="margin-right: 5px"
|
||||
width="20"
|
||||
height="20" />打印单据</el-button
|
||||
>
|
||||
<el-button @click="exportTableToExcel"
|
||||
><img
|
||||
src="/assets/images/Excel.svg"
|
||||
alt=""
|
||||
width="20"
|
||||
height="20" />导出</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="loading" class="loading-mask">
|
||||
<el-icon class="is-loading" color="#409EFC" :size="30">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
<span style="margin-left: 10px">数据加载中...</span>
|
||||
</div>
|
||||
<div id="print-container">
|
||||
<h2
|
||||
style="
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-size: 20pt;
|
||||
padding: 15px;
|
||||
font-weight: bold;
|
||||
">
|
||||
销售统计报表
|
||||
</h2>
|
||||
<table
|
||||
v-show="!loading"
|
||||
style="
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-family: 宋体;
|
||||
">
|
||||
<!-- 表头 -->
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="border: 1px solid #000; padding: 8px">序号</th>
|
||||
<th style="border: 1px solid #000; padding: 8px">服务项目</th>
|
||||
<th style="border: 1px solid #000; padding: 8px">单价(元)</th>
|
||||
<th style="border: 1px solid #000; padding: 8px">数量</th>
|
||||
<th style="border: 1px solid #000; padding: 8px">小计(元)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- 新增空状态 -->
|
||||
<tr v-if="showEmpty">
|
||||
<td
|
||||
colspan="4"
|
||||
style="text-align: center; color: #999; padding: 20px">
|
||||
未查询到相关数据
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 分类数据 -->
|
||||
<template
|
||||
v-for="category in statsData.categories"
|
||||
:key="category.categoryName">
|
||||
<tr>
|
||||
<td
|
||||
colspan="5"
|
||||
style="font-weight: bold; padding: 8px; text-align: center">
|
||||
{{ category.categoryName }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
v-for="(service, index) in category.services"
|
||||
:key="service.serviceName">
|
||||
<td style="padding: 8px">{{ index + 1 }}</td>
|
||||
<td style="border: 1px solid #000; padding: 8px">
|
||||
{{ service.serviceName }}
|
||||
</td>
|
||||
<td
|
||||
style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.price.toFixed(2) }}
|
||||
</td>
|
||||
<td
|
||||
style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.quantity }}
|
||||
</td>
|
||||
<td
|
||||
style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.subtotal.toFixed(2) }}
|
||||
</td>
|
||||
</tr>
|
||||
<!-- <tr style="font-weight: bold">
|
||||
<td colspan="2" style="border: 1px solid #000; padding: 8px">
|
||||
分类合计
|
||||
</td>
|
||||
<td
|
||||
style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ category.totalQuantity }}
|
||||
</td>
|
||||
<td
|
||||
style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ category.totalAmount.toFixed(2) }}
|
||||
</td>
|
||||
</tr> -->
|
||||
</template>
|
||||
|
||||
<!-- 其他服务 -->
|
||||
<tr v-if="statsData.otherCategory.services.length">
|
||||
<td colspan="5" style="font-weight: bold; padding: 8px">
|
||||
{{ statsData.otherCategory.categoryName }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
v-if="statsData.otherCategory.services.length"
|
||||
v-for="(service, index) in statsData.otherCategory.services"
|
||||
:key="'other-' + service.serviceName">
|
||||
<td style="padding: 8px">{{ index + 1 }}</td>
|
||||
<td style="border: 1px solid #000; padding: 8px">
|
||||
{{ service.serviceName }}
|
||||
</td>
|
||||
<td style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.price.toFixed(2) }}
|
||||
</td>
|
||||
<td style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.quantity }}
|
||||
</td>
|
||||
<td style="border: 1px solid #000; text-align: right; padding: 8px">
|
||||
{{ service.subtotal.toFixed(2) }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 总计行 -->
|
||||
<tr>
|
||||
<td
|
||||
colspan="3"
|
||||
style="
|
||||
border: 1px solid #000;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
">
|
||||
数量和金额总计
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
border: 1px solid #000;
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
">
|
||||
{{ statsData.grandTotalQuantity }}
|
||||
</td>
|
||||
<td
|
||||
style="
|
||||
border: 1px solid #000;
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
">
|
||||
{{ statsData.grandTotalAmount.toFixed(2) }} 元
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { Loading } from "@element-plus/icons-vue";
|
||||
import request from "@/lib/request";
|
||||
import dayjs from "dayjs";
|
||||
import * as XLSX from "xlsx";
|
||||
|
||||
interface ServiceStatsItem {
|
||||
serviceName: string;
|
||||
price: number;
|
||||
unit: string;
|
||||
quantity: number;
|
||||
subtotal: number;
|
||||
}
|
||||
|
||||
interface CategoryStats {
|
||||
categoryName: string;
|
||||
services: ServiceStatsItem[];
|
||||
totalQuantity: number;
|
||||
totalAmount: number;
|
||||
}
|
||||
|
||||
interface StatsResponse {
|
||||
categories: CategoryStats[];
|
||||
otherCategory: CategoryStats;
|
||||
grandTotalQuantity: number;
|
||||
grandTotalAmount: number;
|
||||
}
|
||||
const print = {
|
||||
id: "print-container",
|
||||
};
|
||||
// 保持原有响应式数据结构
|
||||
const loading = ref(false);
|
||||
const searchForm = ref({
|
||||
dateRange: [
|
||||
dayjs().startOf("day").format("YYYY-MM-DD 00:00:00"),
|
||||
dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
|
||||
] as string[],
|
||||
serviceName: "",
|
||||
categoryName: "",
|
||||
});
|
||||
|
||||
const statsData = ref<StatsResponse>({
|
||||
categories: [],
|
||||
otherCategory: {
|
||||
categoryName: "其他服务",
|
||||
services: [],
|
||||
totalQuantity: 0,
|
||||
totalAmount: 0,
|
||||
},
|
||||
grandTotalQuantity: 0,
|
||||
grandTotalAmount: 0,
|
||||
});
|
||||
|
||||
const categories = ref<Array<{ id: number; name: string }>>([]);
|
||||
const showEmpty = computed(
|
||||
() =>
|
||||
statsData.value?.categories?.length === 0 &&
|
||||
statsData.value.otherCategory.services.length === 0
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
await fetchCategories();
|
||||
await query();
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
});
|
||||
|
||||
const fetchCategories = async () => {
|
||||
try {
|
||||
const res = await request().get("/public/service-categories");
|
||||
categories.value = res.data.map((item: any) => ({
|
||||
id: item.value,
|
||||
name: item.label,
|
||||
}));
|
||||
} catch (error) {
|
||||
ElMessage.error("分类加载失败");
|
||||
}
|
||||
};
|
||||
|
||||
const query = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
|
||||
const params = {
|
||||
startDate: searchForm.value.dateRange[0],
|
||||
endDate: searchForm.value.dateRange[1],
|
||||
serviceName: searchForm.value.serviceName,
|
||||
categoryName: searchForm.value.categoryName,
|
||||
};
|
||||
|
||||
const res = await request().get("/stats/servicesStats", { params });
|
||||
statsData.value = res.data || res;
|
||||
} catch (error) {
|
||||
ElMessage.error(`查询失败: ${(error as Error).message}`);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
searchForm.value = {
|
||||
dateRange: [
|
||||
dayjs().startOf("day").format("YYYY-MM-DD 00:00:00"),
|
||||
dayjs().format("YYYY-MM-DD 23:59:59"),
|
||||
],
|
||||
serviceName: "",
|
||||
categoryName: "",
|
||||
};
|
||||
query();
|
||||
};
|
||||
|
||||
const dateChange = (val: string[]) => {
|
||||
if (val?.length === 2) {
|
||||
searchForm.value.dateRange = val;
|
||||
}
|
||||
};
|
||||
|
||||
const handleError = (error: unknown) => {
|
||||
ElMessage({
|
||||
type: "error",
|
||||
message: "系统异常,请稍后重试",
|
||||
duration: 3000,
|
||||
});
|
||||
};
|
||||
|
||||
function exportTableToExcel() {
|
||||
const table = document.querySelector(
|
||||
"#print-container table"
|
||||
) as HTMLTableElement;
|
||||
if (!table) {
|
||||
console.error("找不到表格");
|
||||
return;
|
||||
}
|
||||
|
||||
// 将 HTML 表格转换为 worksheet
|
||||
const worksheet = XLSX.utils.table_to_sheet(table, {
|
||||
raw: true,
|
||||
});
|
||||
|
||||
// 获取范围
|
||||
const range = XLSX.utils.decode_range(worksheet["!ref"]!);
|
||||
|
||||
// 遍历每个单元格,设置样式
|
||||
for (let R = range.s.r; R <= range.e.r; ++R) {
|
||||
for (let C = range.s.c; C <= range.e.c; ++C) {
|
||||
const cellAddress = XLSX.utils.encode_cell({ r: R, c: C });
|
||||
const cell = worksheet[cellAddress];
|
||||
if (!cell || !cell.v) continue;
|
||||
|
||||
// 是否是最后一行(数量和金额总计行)
|
||||
const isLastRow = R === range.e.r;
|
||||
|
||||
cell.s = {
|
||||
alignment: {
|
||||
horizontal: "center",
|
||||
vertical: "center",
|
||||
wrapText: true,
|
||||
},
|
||||
font: {
|
||||
bold: isLastRow, // 最后一行加粗
|
||||
sz: 12,
|
||||
},
|
||||
border: {
|
||||
top: { style: "thin", color: { rgb: "000000" } },
|
||||
bottom: { style: "thin", color: { rgb: "000000" } },
|
||||
left: { style: "thin", color: { rgb: "000000" } },
|
||||
right: { style: "thin", color: { rgb: "000000" } },
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 创建工作簿并导出
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "销售统计");
|
||||
XLSX.writeFile(workbook, "销售统计报表.xlsx");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.loading-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.is-loading {
|
||||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid #000;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
text-align: center !important;
|
||||
}
|
||||
@media print {
|
||||
/* 移除全局布局影响 */
|
||||
body,
|
||||
html {
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
margin: 2mm !important; /* 添加安全边距 */
|
||||
}
|
||||
|
||||
#print-container {
|
||||
width: auto !important; /* 改为自动宽度 */
|
||||
margin: 0 auto !important; /* 居中显示 */
|
||||
font-size: 12pt !important; /* 调整字号 */
|
||||
min-height: 297mm;
|
||||
}
|
||||
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* 优化单元格内边距 */
|
||||
td,
|
||||
th {
|
||||
padding: 4px 2mm !important;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
}
|
||||
|
||||
tr,
|
||||
td {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
#print-container {
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 5mm !important;
|
||||
font-size: 14pt;
|
||||
color: #000 !important;
|
||||
font-family: Microsoft YaHei, "SimSun", serif !important;
|
||||
}
|
||||
/* 添加表格布局优化 */
|
||||
table {
|
||||
width: 100% !important;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse !important;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 10px 2mm !important;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
218
frontEnd/src/pages/system/menue/index.vue
Normal file
218
frontEnd/src/pages/system/menue/index.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="菜单管理"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" :inline="true" label-position="right">
|
||||
<el-form-item label="菜单名:">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入菜单名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单路径:">
|
||||
<el-input
|
||||
v-model="searchForm.path"
|
||||
placeholder="请输入菜单路径"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button type="primary" @click="add" size="small"
|
||||
><el-icon> <CirclePlus /> </el-icon>新增</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table
|
||||
:option="tableOption"
|
||||
ref="table"
|
||||
style="width: 100%"
|
||||
row-key="id"
|
||||
:indent="30"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
:tree-props="{ children: 'children' }">
|
||||
<template #colunm>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="菜单名"
|
||||
align="center"
|
||||
width="180" />
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="创建时间"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column label="图标" width="180" align="center">
|
||||
<template #default="scope">
|
||||
<el-icon>
|
||||
<component :is="scope.row.icon"></component>
|
||||
</el-icon>
|
||||
<span style="padding: 0 15px">{{ scope.row.icon }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="path"
|
||||
label="路径"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column label="是否显示" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.show"
|
||||
size="large"
|
||||
width="65px"
|
||||
inline-prompt
|
||||
active-text="是"
|
||||
inactive-text="否" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
#default="scope"
|
||||
width="300"
|
||||
label="操作"
|
||||
align="center">
|
||||
<el-button size="small" type="primary" @click="examine(scope.row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button size="small" type="warning" @click="update(scope.row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="deleteData(scope.row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="50%"
|
||||
:before-close="handleDialogClose"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<addOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
:data="currentMenue"
|
||||
@updateData="getUserData"
|
||||
v-if="
|
||||
pageVisibleState.showPageType.edit ||
|
||||
pageVisibleState.showPageType.add
|
||||
"></addOrEdit>
|
||||
<menueView
|
||||
v-if="pageVisibleState.showPageType.view"
|
||||
:data="currentMenue"></menueView>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted, ref } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import addOrEdit from "./page/addOrEdit/addOrEdit.vue";
|
||||
import menueView from "./page/view/view.vue";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
import api from "@/lib/request";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "新增菜单",
|
||||
edit: "菜单编辑",
|
||||
view: "菜单查看",
|
||||
});
|
||||
const searchForm = reactive({
|
||||
name: "",
|
||||
path: "",
|
||||
});
|
||||
|
||||
let currentMenue = ref<systemMenueType>({});
|
||||
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/system-menue/list",
|
||||
searchUrl: "/system-menue/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
function add() {
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
|
||||
function examine(row: systemMenueType) {
|
||||
currentMenue.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.view = true;
|
||||
}
|
||||
function update(row: systemMenueType) {
|
||||
currentMenue.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.edit = true;
|
||||
}
|
||||
async function deleteData(row: systemMenueType) {
|
||||
ElMessageBox.confirm("确定要删除该菜单吗?", "警告", {
|
||||
type: "error",
|
||||
}).then(async () => {
|
||||
let respone = await api().get("/system-menue/delete?id=" + row.id);
|
||||
if (respone.code === 200) {
|
||||
ElMessage.success("菜单删除成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("list");
|
||||
ElMessage.success("重置成功!");
|
||||
}
|
||||
|
||||
function handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
}
|
||||
function addConfim() {
|
||||
ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
let res = await api().post("/system-menue/add", currentMenue.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("添加成功");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
});
|
||||
}
|
||||
function getUserData(newVal: systemMenueType) {
|
||||
currentMenue.value = { ...newVal };
|
||||
}
|
||||
async function editConfim() {
|
||||
ElMessageBox.confirm("确认该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(async () => {
|
||||
let respone = await api().post("/system-menue/update", currentMenue.value);
|
||||
if (respone.code == 200) {
|
||||
ElMessage.success("修改成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
81
frontEnd/src/pages/system/menue/page/addOrEdit/addOrEdit.vue
Normal file
81
frontEnd/src/pages/system/menue/page/addOrEdit/addOrEdit.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<el-form
|
||||
v-loading="loading"
|
||||
element-loading-text="初始化数据中..."
|
||||
:model="menueForm"
|
||||
:inline="true"
|
||||
label-suffix=":"
|
||||
label-width="80px">
|
||||
<el-form-item label="菜单名">
|
||||
<el-input v-model="menueForm.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="路径">
|
||||
<el-input v-model="menueForm.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属">
|
||||
<el-select v-model="menueForm.parentId">
|
||||
<el-option label="顶级" :value="0"></el-option>
|
||||
<el-option
|
||||
:label="item.name"
|
||||
:value="((item.id) as number)"
|
||||
v-for="(item, index) in menues"
|
||||
:key="index">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="图标">
|
||||
<el-input v-model="menueForm.icon"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否显示">
|
||||
<el-switch v-model="menueForm.show"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
import api from "@/lib/request";
|
||||
|
||||
const props = defineProps<{
|
||||
data?: systemMenueType;
|
||||
executeType?: string;
|
||||
}>();
|
||||
const emits = defineEmits(["updateData"]);
|
||||
let menues = ref<systemMenueType[]>([]);
|
||||
let loading = ref(true);
|
||||
let menueForm = ref<systemMenueType>({
|
||||
name: "",
|
||||
path: "",
|
||||
parentId: 0,
|
||||
icon: "",
|
||||
show: true,
|
||||
});
|
||||
|
||||
if (props.executeType === "edit") {
|
||||
menueForm.value = { ...props.data };
|
||||
}
|
||||
|
||||
watch(
|
||||
() => menueForm,
|
||||
(newVal) => {
|
||||
emits("updateData", newVal.value);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
let respone = await api().get("/system-menue/list?all=true");
|
||||
menues.value = respone.data.list;
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-input__wrapper {
|
||||
width: 200px;
|
||||
}
|
||||
.el-select {
|
||||
width: 192px;
|
||||
}
|
||||
</style>
|
||||
47
frontEnd/src/pages/system/menue/page/view/view.vue
Normal file
47
frontEnd/src/pages/system/menue/page/view/view.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<el-descriptions
|
||||
title="个人信息"
|
||||
style="padding: 15px"
|
||||
border
|
||||
size="large"
|
||||
:column="2">
|
||||
<el-descriptions-item>
|
||||
<template #label> 菜单名 </template>{{ menue.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label> 路径 </template>{{ menue.path }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label> 所属菜单 </template
|
||||
>{{ menue.parentId }}</el-descriptions-item
|
||||
>
|
||||
<el-descriptions-item>
|
||||
<template #label> 图标 </template>
|
||||
<el-icon>
|
||||
<component :is="menue.icon" />
|
||||
</el-icon>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>是否显示 </template>
|
||||
<el-tag type="success" v-if="menue.show">显示</el-tag>
|
||||
<el-tag type="danger" v-else>隐藏</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
const props = defineProps<{
|
||||
data: systemMenueType;
|
||||
}>();
|
||||
const menue = props.data;
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-descriptions__label) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-icon {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
212
frontEnd/src/pages/system/role/index.vue
Normal file
212
frontEnd/src/pages/system/role/index.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="角色管理"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form
|
||||
:model="searchForm"
|
||||
:inline="true"
|
||||
label-position="right"
|
||||
:label-suffix="':'">
|
||||
<!-- <el-form-item label="所属角色">
|
||||
<el-select
|
||||
v-model="searchForm.roleValue"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择角色"
|
||||
style="width: 150px">
|
||||
<el-option
|
||||
v-for="item in menues"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="String(item.id)">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="角色名">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入角色名"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button size="small" type="primary" @click="add">
|
||||
<el-icon> <CirclePlus /> </el-icon>新增
|
||||
</el-button>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table :option="tableOption" ref="table">
|
||||
<el-table-column type="index"></el-table-column>
|
||||
<el-table-column prop="name" label="角色名" align="center" />
|
||||
<el-table-column prop="createDate" label="创建时间" align="center" />
|
||||
<el-table-column
|
||||
prop="updateData"
|
||||
label="最后更改时间"
|
||||
align="center" />
|
||||
<!-- <el-table-column label="角色状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.roleState"
|
||||
size="large"
|
||||
width="65px"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="roleStateChange"
|
||||
inactive-text="禁用" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column #default="scope" label="操作" align="center">
|
||||
<el-button size="small" type="primary" @click="examine(scope.row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button size="small" type="warning" @click="update(scope.row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="deleteData(scope.row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-table-column>
|
||||
</base-table>
|
||||
</el-card>
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="50%"
|
||||
:before-close="handleDialogClose"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<addOrEdite
|
||||
:data="currentRole"
|
||||
@updateData="getRoleData"
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
v-if="
|
||||
pageVisibleState.showPageType.edit ||
|
||||
pageVisibleState.showPageType.add
|
||||
"></addOrEdite>
|
||||
<roleView :data="currentRole" v-if="pageVisibleState.showPageType.view">
|
||||
</roleView>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted, ref } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import api from "@/lib/request";
|
||||
import { roleType } from "@/types/role";
|
||||
import roleView from "./page/view.vue";
|
||||
import addOrEdite from "./page/addOrEdit.vue";
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "新增角色",
|
||||
edit: "角色编辑",
|
||||
view: "角色查看",
|
||||
});
|
||||
|
||||
let currentRole = ref<roleType>({});
|
||||
let menues = ref<systemMenueType[]>();
|
||||
|
||||
const searchForm = reactive({
|
||||
roleValue: "",
|
||||
name: "",
|
||||
});
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/role/list",
|
||||
searchUrl: "/role/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
let respone = await api().get("/system-menue/list?all=true");
|
||||
menues.value = respone.data.list;
|
||||
});
|
||||
|
||||
function examine(row: roleType) {
|
||||
currentRole.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.view = true;
|
||||
}
|
||||
function update(row: roleType) {
|
||||
currentRole.value = row;
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.edit = true;
|
||||
}
|
||||
async function deleteData(row: roleType) {
|
||||
ElMessageBox.confirm("确定要删除该用户吗?", "警告", {
|
||||
type: "error",
|
||||
}).then(async () => {
|
||||
let respone = await api().get("/role/delete?id=" + row.id);
|
||||
if (respone.code === 200) {
|
||||
ElMessage.success("角色删除成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(respone.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
function resetSearch() {
|
||||
searchForm.roleValue = "";
|
||||
searchForm.name = "";
|
||||
table.value.methods.setDataType("list");
|
||||
ElMessage.success("重置成功!");
|
||||
}
|
||||
function handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
}
|
||||
function addConfim() {
|
||||
ElMessageBox.confirm("确定增加数据吗?", "提示", { type: "warning" }).then(
|
||||
async () => {
|
||||
let res = await api().post("/role/add", currentRole.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("添加成功");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
function editConfim() {
|
||||
ElMessageBox.confirm("确定要修改数据吗?", "提示", { type: "warning" }).then(
|
||||
async () => {
|
||||
let respone = await api().post("/role/update", currentRole.value);
|
||||
if (respone.code == 200) {
|
||||
ElMessage.success("修改成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getRoleData(newVal: roleType) {
|
||||
currentRole.value = { ...newVal };
|
||||
}
|
||||
|
||||
function add() {
|
||||
pageVisibleState.show2LevelPage.value = true;
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
|
||||
function roleStateChange(state: any) {}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
75
frontEnd/src/pages/system/role/page/addOrEdit.vue
Normal file
75
frontEnd/src/pages/system/role/page/addOrEdit.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<el-form v-loading="loading" element-loading-text="初始化数据中..." :model="roleForm" :inline="true" label-suffix=":"
|
||||
label-width="80px">
|
||||
<el-form-item label="角色名">
|
||||
<el-input v-model="roleForm.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用">
|
||||
<el-switch v-model="roleForm.roleState" :active-value="1" :inactive-value="0"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item style="width: 100%;" label="权限">
|
||||
<el-tree :data="roles" :props="treeProps" show-checkbox default-expand-all node-key="id"
|
||||
:default-checked-keys="roleForm.values?.split(',')" @check="handleCheckChange" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
import api from "@/lib/request";
|
||||
import { roleType } from "@/types/role";
|
||||
|
||||
const props = defineProps<{
|
||||
data?: roleType;
|
||||
executeType?: string;
|
||||
}>();
|
||||
const emits = defineEmits(["updateData"]);
|
||||
let roles = ref<systemMenueType[]>([]);
|
||||
let loading = ref(true);
|
||||
let treeProps = { label: "name", children: "children" };
|
||||
let auths = ref<string[]>([]);
|
||||
|
||||
let roleForm = ref<roleType>({
|
||||
name: "",
|
||||
roleState: 1,
|
||||
values: ''
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
let respone = await api().get('/system-menue/list');
|
||||
roles.value = respone.data.list;
|
||||
|
||||
loading.value = false;
|
||||
|
||||
if (props.executeType === "edit") {
|
||||
roleForm.value = { ...props.data };
|
||||
auths.value = roleForm.value.values?.split(',') as string[];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => roleForm,
|
||||
(newVal) => {
|
||||
emits("updateData", newVal.value);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
})
|
||||
|
||||
function handleCheckChange(val: string[], checkVal: any) {
|
||||
auths.value = checkVal.checkedKeys.filter(item => String(item));
|
||||
roleForm.value.values = auths.value.join(',');
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-input__wrapper {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 192px;
|
||||
}
|
||||
</style>
|
||||
@/types/systemMenue
|
||||
61
frontEnd/src/pages/system/role/page/view.vue
Normal file
61
frontEnd/src/pages/system/role/page/view.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<el-descriptions
|
||||
title="角色信息"
|
||||
style="padding: 15px"
|
||||
border
|
||||
size="large"
|
||||
:column="2">
|
||||
<el-descriptions-item>
|
||||
<template #label> 角色名 </template>{{ theRoleInfo.name }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>是否启用 </template>
|
||||
<el-tag type="success" v-if="theRoleInfo.roleState">启用</el-tag>
|
||||
<el-tag type="danger" v-else>禁用</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<label>角色权限:</label>
|
||||
<el-tree
|
||||
:data="roles"
|
||||
:props="treeProps"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:default-checked-keys="theRoleInfo.values?.split(',')"
|
||||
default-expand-all />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { systemMenueType } from "@/types/systemMenue";
|
||||
import { roleType } from "@/types/role";
|
||||
import { ref, onMounted } from "vue";
|
||||
import api from "@/lib/request";
|
||||
const props = defineProps<{
|
||||
data: roleType;
|
||||
}>();
|
||||
const role = props.data;
|
||||
let roles = ref<systemMenueType[]>([]);
|
||||
let loading = ref(true);
|
||||
let treeProps = { label: "name", children: "children" };
|
||||
let theRoleInfo = ref<roleType>({});
|
||||
|
||||
theRoleInfo.value = { ...props.data };
|
||||
|
||||
onMounted(async () => {
|
||||
let respone = await api().get("/system-menue/list");
|
||||
roles.value = respone.data.list;
|
||||
loading.value = false;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-descriptions__label) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.el-icon {
|
||||
margin: 0 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
279
frontEnd/src/pages/system/user/index.vue
Normal file
279
frontEnd/src/pages/system/user/index.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<baseTableHeader
|
||||
title="用户管理"
|
||||
@resetSearch="resetSearch"
|
||||
@search="search">
|
||||
<template #content>
|
||||
<el-form :model="searchForm" :inline="true" label-position="right">
|
||||
<el-form-item label="姓名:">
|
||||
<el-input
|
||||
v-model="searchForm.name"
|
||||
placeholder="请输入姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别:">
|
||||
<el-radio-group v-model="searchForm.sex">
|
||||
<el-radio value="男">男</el-radio>
|
||||
<el-radio value="女">女</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号:">
|
||||
<el-input
|
||||
v-model="searchForm.phone"
|
||||
placeholder="请输入手机号"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template #operateBtns>
|
||||
<el-button size="small" type="primary" @click="add">
|
||||
<template #icon>
|
||||
<el-icon>
|
||||
<CirclePlus />
|
||||
</el-icon> </template
|
||||
>新增</el-button
|
||||
>
|
||||
</template>
|
||||
</baseTableHeader>
|
||||
</el-row>
|
||||
<el-card style="margin-top: 8px">
|
||||
<base-table :option="tableOption" ref="table">
|
||||
<template #colunm>
|
||||
<el-table-column type="index" width="50"></el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="姓名"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column prop="sex" label="性别" align="center" />
|
||||
<el-table-column prop="role" label="所属角色" align="center">
|
||||
<template #default="scope">
|
||||
{{
|
||||
roleList?.find(
|
||||
(item) => Number(item.id) === Number(scope.row.role)
|
||||
)?.name || "无"
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="账户状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.userState"
|
||||
size="large"
|
||||
width="65px"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
@change="stateVal => userStatChange(stateVal as boolean, scope.row)"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
inactive-text="禁用" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="phone" label="手机号" align="center" />
|
||||
<el-table-column
|
||||
prop="createDate"
|
||||
label="创建时间"
|
||||
width="180"
|
||||
align="center" />
|
||||
<el-table-column #default="scope" width="300">
|
||||
<el-button size="small" type="primary" @click="view(scope.row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button size="small" type="warning" @click="edit(scope.row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="deleteData(scope.row)"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button size="small" type="danger" @click="resetPwd(scope.row)"
|
||||
>重置密码</el-button
|
||||
>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</base-table>
|
||||
</el-card>
|
||||
|
||||
<base-curd-dialog
|
||||
v-model="pageVisibleState.show2LevelPage.value"
|
||||
:title="pageVisibleState.dialogTitle.value"
|
||||
width="50%"
|
||||
:before-close="handleDialogClose"
|
||||
@addConfim="addConfim"
|
||||
@editConfim="editConfim"
|
||||
@closeConfirm="handleDialogClose"
|
||||
:showPageType="pageVisibleState.showPageType">
|
||||
<template #content>
|
||||
<userAddOrEdit
|
||||
:executeType="pageVisibleState.executeType.value"
|
||||
v-if="
|
||||
pageVisibleState.showPageType.edit ||
|
||||
pageVisibleState.showPageType.add
|
||||
"
|
||||
:data="(currentUser as userType)"
|
||||
@updateData="getUserData">
|
||||
</userAddOrEdit>
|
||||
<userView
|
||||
v-if="pageVisibleState.showPageType.view"
|
||||
:data="(currentUser as userType)">
|
||||
</userView>
|
||||
</template>
|
||||
</base-curd-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { resetParams } from "@/util/globalMethods";
|
||||
import { userType } from "@/types/user";
|
||||
import { globalState } from "@/store";
|
||||
import userAddOrEdit from "./page/userAddOrEdit.vue";
|
||||
import userView from "@/pages/publicPages/user/userView.vue";
|
||||
import api from "@/lib/request";
|
||||
import pageVisible from "@/components/curdDialog/pageVisibleState";
|
||||
import { roleDataList } from "@/lib/api/publicApiList";
|
||||
import { roleType } from "@/types/role";
|
||||
import { tableOptionType } from "@/types/table";
|
||||
const pageVisibleState = new pageVisible({
|
||||
add: "新增用户",
|
||||
edit: "用户编辑",
|
||||
view: "信息查看",
|
||||
});
|
||||
|
||||
const globalStateStore = globalState();
|
||||
const searchForm = reactive({
|
||||
name: "",
|
||||
sex: "",
|
||||
phone: "",
|
||||
});
|
||||
|
||||
let currentUser = ref<userType>({});
|
||||
let roleList = ref<roleType[]>();
|
||||
let table = ref();
|
||||
let tableOption = ref<tableOptionType>({
|
||||
url: "/user/list",
|
||||
searchUrl: "/user/query",
|
||||
searchParams: searchForm,
|
||||
executeType: "list",
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
roleList.value = await roleDataList();
|
||||
});
|
||||
|
||||
function view(row: userType) {
|
||||
pageVisibleState.showPageType.view = true;
|
||||
currentUser.value = row;
|
||||
}
|
||||
function edit(row: userType) {
|
||||
pageVisibleState.showPageType.edit = true;
|
||||
|
||||
currentUser.value = row;
|
||||
}
|
||||
function add() {
|
||||
pageVisibleState.showPageType.add = true;
|
||||
}
|
||||
|
||||
function addConfim() {
|
||||
ElMessageBox.confirm("确定新增该条信息吗?", "提示", {
|
||||
type: "warning",
|
||||
}).then(() => {
|
||||
globalStateStore.setGlobalLoadingShow(true, "正在提交信息...");
|
||||
api()
|
||||
.post("/user/add", { ...currentUser.value })
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
pageVisibleState.showPageType.add = false;
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
ElMessage.success("新增成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
globalStateStore.setGlobalLoadingShow(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getUserData(newVal: any) {
|
||||
currentUser.value = { ...newVal.value };
|
||||
}
|
||||
|
||||
function editConfim() {
|
||||
ElMessageBox.confirm("确定更改数据吗?", "提示", { type: "warning" }).then(
|
||||
() => {
|
||||
api()
|
||||
.post("/user/update", currentUser.value)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("更改成功!");
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
table.value.methods.setDataType("list");
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function deleteData(row: userType) {
|
||||
ElMessageBox.confirm("确定要删除该用户吗?", "警告", {
|
||||
type: "error",
|
||||
}).then(() => {
|
||||
api()
|
||||
.get("/user/delete?id=" + row.id)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(` ${row.name} 删除成功!`);
|
||||
table.value.methods.setDataType("list");
|
||||
} else {
|
||||
ElMessage.warning(res.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function search() {
|
||||
table.value.methods.setDataType("search");
|
||||
}
|
||||
|
||||
function resetSearch() {
|
||||
resetParams(searchForm);
|
||||
table.value.methods.setDataType("reset");
|
||||
ElMessage.success("重置成功!");
|
||||
}
|
||||
|
||||
function resetPwd(row: userType) {
|
||||
ElMessageBox.confirm("确定要重置该用户的密码吗?", "警告", {
|
||||
type: "error",
|
||||
}).then(() => {
|
||||
api()
|
||||
.get("/user/resetPwd?id=" + row.id)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessageBox.confirm(
|
||||
` ${row.name} 的密码重置成功为123456,请告知用户!`,
|
||||
"提示",
|
||||
{ type: "success" }
|
||||
);
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
ElMessage.success("密码重置成功!");
|
||||
});
|
||||
}
|
||||
function handleDialogClose() {
|
||||
pageVisibleState.show2LevelPage.value = false;
|
||||
}
|
||||
function userStatChange(state: boolean, data: userType) {
|
||||
api()
|
||||
.post("/user/update", {
|
||||
userState: state ? 1 : 0,
|
||||
id: data.id,
|
||||
})
|
||||
.then(() => {
|
||||
ElMessage.success("用户状态更改成功!");
|
||||
table.value.methods.setDataType("list");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
143
frontEnd/src/pages/system/user/page/userAddOrEdit.vue
Normal file
143
frontEnd/src/pages/system/user/page/userAddOrEdit.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<el-form
|
||||
:model="user"
|
||||
label-width="100px"
|
||||
:inline="true"
|
||||
label-suffix=":"
|
||||
v-loading="loading"
|
||||
element-loading-text="正在初始化数据...">
|
||||
<el-form-item label="姓名">
|
||||
<el-input :prefix-icon="User" v-model="user.name" placeholder="姓名">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别">
|
||||
<el-radio-group v-model="user.sex">
|
||||
<el-radio value="男">男</el-radio>
|
||||
<el-radio value="女">女</el-radio>
|
||||
<el-radio value="保密">保密</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="电话">
|
||||
<el-input
|
||||
:prefix-icon="Iphone"
|
||||
v-model="user.phone"
|
||||
placeholder="电话"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属角色">
|
||||
<el-select
|
||||
v-model="user.role"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择角色"
|
||||
style="width: 230px">
|
||||
<el-option
|
||||
v-for="item in roleList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="String(item.id)"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="生日">
|
||||
<el-date-picker
|
||||
format="YYYYH-MM-DD"
|
||||
v-model="user.birthday"
|
||||
type="date"
|
||||
placeholder="生日"
|
||||
size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所在区域">
|
||||
<el-cascader
|
||||
:options="pcaTextArrData"
|
||||
v-model="selectedOptions"
|
||||
@change="pcaChange"></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址">
|
||||
<el-input
|
||||
:prefix-icon="Location"
|
||||
v-model="user.address"
|
||||
placeholder="请输入详细地址"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="账号状态">
|
||||
<el-switch
|
||||
v-model="user.userState"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="启用"
|
||||
width="65px"
|
||||
inline-prompt
|
||||
inactive-text="禁用"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { userType } from "@/types/user";
|
||||
// @ts-ignore
|
||||
import { pcaTextArr } from "element-china-area-data";
|
||||
import { Avatar, Location, Iphone, User } from "@element-plus/icons-vue";
|
||||
import { roleType } from "@/types/role";
|
||||
import { roleDataList } from "@/lib/api/publicApiList";
|
||||
|
||||
const pcaTextArrData = ref(pcaTextArr);
|
||||
const selectedOptions = ref([]);
|
||||
const props = defineProps<{
|
||||
data?: userType;
|
||||
executeType?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(["updateData"]);
|
||||
|
||||
let loading = ref(true);
|
||||
let roleList = ref<roleType[]>();
|
||||
let user = ref<userType>({
|
||||
createDate: "",
|
||||
name: "",
|
||||
sex: "男",
|
||||
phone: "",
|
||||
userState: 1,
|
||||
role: "",
|
||||
birthday: "",
|
||||
province: "",
|
||||
city: "",
|
||||
area: "",
|
||||
address: "",
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
roleList.value = await roleDataList();
|
||||
|
||||
watch(
|
||||
() => user,
|
||||
(newVal) => {
|
||||
emit("updateData", newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
if (props.executeType === "edit") {
|
||||
user.value = { ...props.data };
|
||||
selectedOptions.value = [
|
||||
user.value.province as never,
|
||||
user.value.city as never,
|
||||
user.value.area as never,
|
||||
];
|
||||
}
|
||||
|
||||
function pcaChange(data: { [key: string]: any }) {
|
||||
user.value.province = data[0];
|
||||
user.value.city = data[1];
|
||||
user.value.area = data[2];
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-input) {
|
||||
width: 230px;
|
||||
}
|
||||
:deep(.el-form-item) {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
267
frontEnd/src/pages/system/user/personal.vue
Normal file
267
frontEnd/src/pages/system/user/personal.vue
Normal file
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="15">
|
||||
<!-- <el-col :span="12">
|
||||
<el-card style="height: 500px" class="info-show">
|
||||
<ul class="info-list">
|
||||
<li class="infor-list-item">
|
||||
<label for="">姓名:</label>
|
||||
<span>{{ userInforStore.userInfor.name }}</span>
|
||||
</li>
|
||||
<li class="infor-list-item">
|
||||
<label for="">性别:</label>
|
||||
<span>{{ userInforStore.userInfor.sex }}</span>
|
||||
</li>
|
||||
<li class="infor-list-item">
|
||||
<label for="">手机号:</label>
|
||||
<span>{{ userInforStore.userInfor.phone }}</span>
|
||||
</li>
|
||||
<li class="infor-list-item">
|
||||
<label for="">生日:</label>
|
||||
<span>{{
|
||||
dayjs(userInforStore.userInfor.birthday).format("YYYY-MM-DD")
|
||||
}}</span>
|
||||
</li>
|
||||
<li class="infor-list-item">
|
||||
<label for="">地址:</label>
|
||||
<span>{{
|
||||
userInforStore.userInfor.province +
|
||||
"/" +
|
||||
userInforStore.userInfor.city +
|
||||
"/" +
|
||||
userInforStore.userInfor.area +
|
||||
"/" +
|
||||
userInforStore.userInfor.address
|
||||
}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<el-divider />
|
||||
</el-card>
|
||||
</el-col> -->
|
||||
<el-col :span="24" v-loading="loading">
|
||||
<el-form :model="tempUserInfor" label-width="120px">
|
||||
<el-form-item label="姓名:">
|
||||
<el-input
|
||||
v-model="tempUserInfor.name"
|
||||
placeholder="请输入你的姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别:">
|
||||
<el-radio-group v-model="tempUserInfor.sex">
|
||||
<el-radio value="男">男</el-radio>
|
||||
<el-radio value="女">女</el-radio>
|
||||
<el-radio value="保密">保密</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="生日:">
|
||||
<el-date-picker
|
||||
v-model="tempUserInfor.birthday"
|
||||
type="date"
|
||||
placeholder="选择你的生日呀"
|
||||
size="large" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号:">
|
||||
<el-input
|
||||
v-model="tempUserInfor.phone"
|
||||
placeholder="请输入你的手机号"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所在区域">
|
||||
<el-cascader
|
||||
:options="pcaTextArrData"
|
||||
v-model="selectedOptions"
|
||||
@change="pcaChange"></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="详细地址:">
|
||||
<el-input
|
||||
v-model="tempUserInfor.address"
|
||||
placeholder="请输入你的地址"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码:">
|
||||
<el-input
|
||||
v-model="tempUserInfor.pwd"
|
||||
placeholder="请输入你的新密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
style="width: 60%"
|
||||
@click="updatePersonInfo"
|
||||
>更新我的信息</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<!-- <el-col :span="24" style="margin-top: 15px">
|
||||
<el-card>
|
||||
<baseEcharts :option="lineStack" style="height: 300px"></baseEcharts>
|
||||
</el-card>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, onMounted, ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { userInfor } from "@/store/user/user";
|
||||
import dayjs from "dayjs";
|
||||
import { pcaTextArr } from "element-china-area-data";
|
||||
import { userType } from "@/types/user";
|
||||
import api from "@/lib/request";
|
||||
import { md5 } from "js-md5";
|
||||
|
||||
const userInforStore = userInfor();
|
||||
const pcaTextArrData = ref(pcaTextArr);
|
||||
let tempUserInfor = ref<userType>({ ...userInforStore.userInfor, pwd: "" });
|
||||
const selectedOptions = ref([
|
||||
tempUserInfor.value.province,
|
||||
tempUserInfor.value.city,
|
||||
tempUserInfor.value.area,
|
||||
]);
|
||||
|
||||
const lineStack = reactive({
|
||||
title: {
|
||||
text: "Stacked Line",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
legend: {
|
||||
data: ["Email", "Union Ads", "Video Ads", "Direct", "Search Engine"],
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "4%",
|
||||
bottom: "3%",
|
||||
containLabel: true,
|
||||
},
|
||||
toolbox: {
|
||||
feature: {
|
||||
saveAsImage: {},
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
boundaryGap: false,
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "Email",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [120, 132, 101, 134, 90, 230, 210],
|
||||
},
|
||||
{
|
||||
name: "Union Ads",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [220, 182, 191, 234, 290, 330, 310],
|
||||
},
|
||||
{
|
||||
name: "Video Ads",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [150, 232, 201, 154, 190, 330, 410],
|
||||
},
|
||||
{
|
||||
name: "Direct",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [320, 332, 301, 334, 390, 330, 320],
|
||||
},
|
||||
{
|
||||
name: "Search Engine",
|
||||
type: "line",
|
||||
stack: "Total",
|
||||
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||
},
|
||||
],
|
||||
});
|
||||
const loading = ref(false);
|
||||
const infoList = ref([
|
||||
{
|
||||
label: "姓名",
|
||||
value: "李嘉图",
|
||||
},
|
||||
{
|
||||
label: "性别",
|
||||
value: "男",
|
||||
},
|
||||
{
|
||||
label: "生日",
|
||||
value: "1996/08/17",
|
||||
},
|
||||
{
|
||||
label: "手机号",
|
||||
value: "1823079420",
|
||||
},
|
||||
{
|
||||
label: "地址",
|
||||
value: "中国贵州省贵阳市",
|
||||
},
|
||||
]);
|
||||
|
||||
function updatePersonInfo() {
|
||||
loading.value = true;
|
||||
let sendData = { ...tempUserInfor.value };
|
||||
|
||||
if (tempUserInfor.value.pwd) {
|
||||
sendData.pwd = md5(tempUserInfor.value.pwd).toLocaleUpperCase();
|
||||
}
|
||||
|
||||
api()
|
||||
.post("/user/update", sendData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
userInfor().setLoginState(res.data.userInfo);
|
||||
loading.value = false;
|
||||
ElMessage.success("用户信息更新成功!");
|
||||
} else {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function pcaChange(data: { [key: string]: any }) {
|
||||
tempUserInfor.value.province = data[0];
|
||||
tempUserInfor.value.city = data[1];
|
||||
tempUserInfor.value.area = data[2];
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.info-show {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
.infor-list-item {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
label {
|
||||
width: 30%;
|
||||
text-align: right;
|
||||
}
|
||||
span {
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sign {
|
||||
display: inline-block;
|
||||
color: rgba($color: #000000, $alpha: 0.5);
|
||||
// transform: scale(0.8);
|
||||
font-size: 0.7rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
:deep(.el-divider--horizontal) {
|
||||
margin: 8px 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user