123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- <template>
- <div class="layout_container wxmall-package">
- <header class="round-header">
- <span>上架时间:</span>
- <CyDateRange />
- <span class="ml-12">
- 套餐状态:
- </span>
- <el-select v-model="inquiry.state" clearable class="w-80">
- <el-option label="已上架" value="ACTIVATED" />
- <el-option label="已下架" value="DEACTIVATED" />
- </el-select>
- <el-divider direction="vertical" />
- <el-button icon="Search" type="primary" @click="queryPackages">查询</el-button>
- <el-button icon="Plus" color="green" @click="beforeAddPackage">上架</el-button>
- </header>
- <div class="layout_main layout_el-table">
- <el-table :data="packageList" stripe>
- <el-table-column prop="name" label="套餐名称" />
- <el-table-column prop="originPrice" label="套餐原价" />
- <el-table-column prop="discountPrice" label="套餐优惠价" />
- <el-table-column prop="description" label="套餐描述" />
- <el-table-column prop="createTime" label="创建时间" />
- <el-table-column prop="createStaffName" label="创建人" />
- <el-table-column label="状态">
- <template #default="{row}">
- <el-switch
- v-model="row.state"
- inline-prompt
- style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
- active-text="已上架"
- inactive-text="已下架"
- active-value="ACTIVATED"
- inactive-value="DEACTIVATED"
- @change="changePackageState(row)"
- ></el-switch>
- </template>
- </el-table-column>
- <el-table-column label="操作">
- <template #default="{row}">
- <el-button
- icon="View"
- type="primary"
- plain
- @click="seePackageDetail(row.id)"
- >
- 查看
- </el-button>
- <el-button
- icon="Edit"
- type="warning"
- plain
- @click="beforeEditPackage(row.id)"
- >
- 编辑
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <el-drawer v-model="showCreation" :title="drawerTitle" size="50%">
- <el-form :model="mainPackage" label-width="auto" :rules="packageMainRules">
- <el-form-item label="套餐名称" prop="name">
- <el-input
- v-model="mainPackage.name"
- maxlength="32"
- show-word-limit
- :disabled="disableEdit"
- />
- </el-form-item>
- <el-form-item label="套餐描述" prop="description">
- <el-input
- v-model="mainPackage.description"
- maxlength="256"
- show-word-limit
- :disabled="disableEdit"
- type="textarea"
- :rows="3"
- />
- </el-form-item>
- <el-form-item label="套餐图片" required prop="fileList">
- <el-upload
- :disabled="disableEdit"
- class="avatar-uploader"
- :show-file-list="false"
- ref="uploadRef"
- v-model:file-list="fileList"
- :action="apiUrl + '/wxmallPackage/createNewPackage'"
- :headers="header"
- :data="creation"
- :limit="1"
- :on-change="handleSelectImage"
- :on-exceed="handleExceed"
- accept="image/jpeg,image/jpg,image/png"
- :auto-upload="false"
- :on-success="onSubmitSuccess"
- >
- <el-image v-if="imageUrl" fit="cover" :src="imageUrl" class="avatar-image" />
- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
- <template #tip>
- <div class="gray-text">
- 请选择小于 200Kb 的 jpg/png 格式的图片。
- </div>
- </template>
- </el-upload>
- </el-form-item>
- </el-form>
- <el-divider>
- <el-tag>套餐明细</el-tag>
- </el-divider>
- <el-form
- v-for="(item, index) in packageItemList"
- :key="index"
- :model="packageItemList[index]"
- inline
- :disabled="disableEdit"
- label-width="auto"
- >
- <el-form-item label="名称" required>
- <el-input v-model="item.hisName" readonly @click="displaySearchPanel(index)"/>
- </el-form-item>
- <el-form-item label="原价">
- <el-input disabled v-model="item.originPrice" type="number" class="w-60" />
- </el-form-item>
- <el-form-item label="优惠价" required>
- <el-input v-model="item.discountPrice" type="number" class="w-60" />
- </el-form-item>
- <el-form-item label="数量" required>
- <el-input v-model.number="item.quantity" class="w-60" />
- </el-form-item>
- <el-form-item v-if="!disableEdit">
- <el-button
- v-if="index === packageItemList.length - 1"
- icon="Plus"
- type="success"
- @click="addNewItemLine(index)"
- >
- 添加
- </el-button>
- <el-button
- icon="Minus"
- type="danger"
- @click="deleteItemLine(index)"
- >
- 删除
- </el-button>
- </el-form-item>
- </el-form>
- <template #footer>
- <div v-if="disableEdit">
- <el-button @click="mode = 'edit'" type="primary" size="default">编辑</el-button>
- </div>
- <div style="flex: auto" v-else>
- <el-button @click="showCreation = false" size="default">取消</el-button>
- <el-button @click="submitUpload" size="default" type="primary">提交</el-button>
- </div>
- </template>
- </el-drawer>
- <Search
- v-if="showSearch"
- med-type="01"
- target="JY"
- title="收费项目查询"
- width="520px"
- show-mall-type
- @close="showSearch = false"
- @click-item="handleClickSearchItem"
- />
- </div>
- </template>
- <script setup>
- import {
- getPackagesByCondition,
- getOriginalPrice,
- getPackageDetail,
- createNewPackage2,
- updatePackageState
- } from "@/api/outpatient/wxmall-package.js";
- import useDateRange from "@/utils/cy-use/useDateRange";
- import {ElMessage, genFileId} from "element-plus";
- import {useUserStore} from "@/pinia/user-store";
- import env from "@/utils/setting";
- import Search from "@/components/search/Index.vue";
- const apiUrl = env.VITE_BASE_URL;
- const {CyDateRange, dateRange} = useDateRange({
- shortcutsIndex: 2,
- clearable: false,
- })
- const inquiry = reactive({
- start: '',
- end: '',
- state: null
- })
- const packageList = ref([])
- function queryPackages() {
- inquiry.start = dateRange.value.start
- inquiry.end = dateRange.value.end
- getPackagesByCondition(inquiry).then(data => {
- packageList.value = data
- })
- }
- function changePackageState(row) {
- updatePackageState(row).then(data => {
- ElMessage.success(data)
- })
- }
- const packageMainRules = reactive({
- name: [ { required: true, message: '请输入套餐名称', trigger: 'blur' } ],
- description: [ { required: true, message: '请输入套餐描述', trigger: 'blur' } ],
- })
- const mode = ref('see')
- const drawerTitle = computed(() => {
- if (mode.value === 'add') {
- return '上架套餐'
- }
- if (mode.value === 'see') {
- return '套餐详情'
- }
- return '编辑套餐'
- })
- const disableEdit = computed(() => {
- return mode.value === 'see'
- })
- const showCreation = ref(false)
- const mainPackage = ref({})
- const uploadRef = ref()
- const fileList = ref([])
- const imageUrl = ref('');
- function beforeAddPackage() {
- mode.value = 'add';
- showCreation.value = true
- }
- function handleSelectImage({raw}) {
- if (raw.type !== "image/jpeg" && raw.type !== "image/png") {
- ElMessage.error("请选择 jpg/png 格式的图片!");
- uploadRef.value.clearFiles();
- return
- }
- if (raw.size / 1024 > 200) {
- ElMessage.error("图片大小不能超过 200Kb!");
- uploadRef.value.clearFiles();
- return;
- }
- imageUrl.value = URL.createObjectURL(raw);
- }
- function handleExceed(files) {
- uploadRef.value.clearFiles();
- const file = files[0];
- file.uid = genFileId();
- uploadRef.value.handleStart(file);
- }
- const packageItemList = ref([{quantity: 1}])
- const showSearch = ref(false)
- const currentIndex = ref(0)
- function displaySearchPanel(index) {
- currentIndex.value = index
- showSearch.value = true
- }
- async function handleClickSearchItem(val) {
- packageItemList.value[currentIndex.value].hisCode = val.code
- packageItemList.value[currentIndex.value].hisName = val.name
- packageItemList.value[currentIndex.value].type = val.type
- if (val.type === 'ZL') {
- packageItemList.value[currentIndex.value].originPrice = val.price
- packageItemList.value[currentIndex.value].discountPrice = val.price
- } else {
- await getOriginalPrice(val.type, val.code).then(price => {
- packageItemList.value[currentIndex.value].originPrice = price
- packageItemList.value[currentIndex.value].discountPrice = price
- })
- }
- showSearch.value = false;
- }
- function addNewItemLine(index) {
- let item = packageItemList.value[index]
- if (!isValidItem(item)) {
- return
- }
- packageItemList.value.push({quantity: 1});
- }
- function deleteItemLine(index) {
- packageItemList.value.splice(index, 1);
- }
- function isValidItem(item) {
- if (!item.hisCode) {
- ElMessage.error('请先填写项目名称')
- return false
- }
- if (!item.discountPrice || item.discountPrice < 0) {
- ElMessage.error('项目优惠价不能小于 0')
- return false
- }
- if (!item.quantity || item.quantity < 1) {
- ElMessage.error('项目数量不能小于 1,且必须为 整数')
- return false
- }
- return true;
- }
- const addedItemCode = ref([])
- const header = {
- token: useUserStore().getToken
- }
- const creation = ref({
- mainPackageJson: null,
- packageItemListJson: null
- })
- function submitUpload() {
- addedItemCode.value = []
- if (!mainPackage.value.name) {
- ElMessage.error('套餐名称不能为空')
- return
- }
- if (!mainPackage.value.description) {
- ElMessage.error('套餐描述不能为空')
- return
- }
- if (fileList.value.length === 0 && mode.value === 'add') {
- ElMessage.error('套餐图片不能为空')
- return
- }
- if (packageItemList.value.length === 0) {
- ElMessage.error('套餐明细不能为空')
- return
- }
- for (let i = 0; i < packageItemList.value.length; i++) {
- let item = packageItemList.value[i]
- if (addedItemCode.value.indexOf(item.hisCode) !== -1) {
- ElMessage.error('请勿添加重复项')
- return
- }
- addedItemCode.value.push(item.hisCode)
- if (!isValidItem(item)) {
- return
- }
- }
- creation.value.mainPackageJson = JSON.stringify(mainPackage.value);
- creation.value.packageItemListJson = JSON.stringify(packageItemList.value)
- nextTick(() => {
- if (fileList.value.length > 0) {
- uploadRef.value.submit()
- } else {
- createNewPackage2(creation.value).then(res => {
- onSubmitSuccess(res)
- })
- }
- })
- }
- function resetFormData() {
- mainPackage.value = {}
- packageItemList.value = [{quantity: 1}]
- creation.value = {
- mainPackageJson: null,
- packageItemListJson: null
- }
- }
- function onSubmitSuccess(res) {
- resetFormData()
- nextTick(() => {
- imageUrl.value = ''
- uploadRef.value.clearFiles();
- ElMessage.success('提交成功')
- if (mode.value === 'add') {
- packageList.value.push(res.data)
- } else if (mode.value === 'edit') {
- queryPackages()
- }
- showCreation.value = false
- })
- }
- function seePackageDetail(id) {
- getPackageDetail(id).then(res => {
- mode.value = 'see';
- mainPackage.value = res
- packageItemList.value = res.items
- imageUrl.value = res.thumbPath
- showCreation.value = true
- })
- }
- function beforeEditPackage(id) {
- getPackageDetail(id).then(res => {
- mode.value = 'edit';
- mainPackage.value = res
- packageItemList.value = res.items
- imageUrl.value = res.thumbPath
- showCreation.value = true
- })
- }
- </script>
- <style lang="scss">
- .wxmall-package {
- .ml-12 {
- margin-left: 12px;
- }
- .w-80 {
- width: 80px;
- }
- .w-60 {
- width: 60px;
- }
- .gray-text {
- color: gray;
- }
- .avatar-uploader {
- .el-upload {
- border: 1px dashed var(--el-border-color);
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- transition: var(--el-transition-duration-fast);
- }
- .el-upload:hover {
- border-color: var(--el-color-primary);
- }
- .avatar-uploader-icon {
- font-size: 28px;
- color: #8c939d;
- width: 100px;
- height: 100px;
- text-align: center;
- }
- .avatar-image {
- width: 100px;
- height: 100px;
- }
- }
- .el-form--inline .el-form-item {
- margin-right: 16px;
- }
- }
- </style>
|