add discount page

This commit is contained in:
2026-02-19 17:55:23 +03:30
parent 2ec50d65d7
commit c01c1da7e4
7 changed files with 365 additions and 25 deletions
+12
View File
@@ -0,0 +1,12 @@
import type {TableInput} from "@core/type/baseTable";
import useAxios from "@core/utils/useAxios";
import type { Discount } from '@/model/discount'
export const getDiscountTable = async (params: TableInput) =>
await useAxios.post<Array<Discount>>('/admin/offer_code/table', params)
export const createDiscount = async (obj: Discount) =>
await useAxios.post<Discount>(`/admin/offer_code/create`, obj)
export const updateDiscount = async (id: number, obj: Discount) =>
await useAxios.put<Discount>(`/admin/offer_code/${id}`, obj)
+17
View File
@@ -0,0 +1,17 @@
export interface Discount {
id?: number
code?: string
title?: string
description?: string
start_at?: string
end_at?: string
type?: number
discount_percent?: number
discount_price?: number
is_active?: boolean
use_only?: number
use_count?: number
created_at?: string
updated_at?: string
deleted_at?: string
}
@@ -0,0 +1,54 @@
<template>
<div>
<BasicShowContext title="لیست تخفیفات">
<BaseTable v-bind="tblProps" @register="submit" ref="tbl">
<template #extraHeader>
<BaseButton type="primary" size="small" class="flex" @click="emits('add')">
<div>افزودن تخفیف</div>
<BaseIcon icon="vuesax-linear:user-add" Size="16px" />
</BaseButton>
</template>
<template #action="{ column, record }">
<div class="gap-2 flex justify-center">
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('edit', record)">
<template #title>
<span>ویرایش</span>
</template>
<Icon icon="vuesax-linear:edit" color="#4572E9" />
</a-tooltip>
</div>
</template>
</BaseTable>
</BasicShowContext>
</div>
</template>
<script lang="tsx" setup>
import type { TableInput } from '@core/type/baseTable'
import useBaseTable from '@core/components/BaseTableOld/hooks/useBaseTable'
import Icon from '@core/components/BaseIcon/src/Icon.vue'
import { cols } from '../hooks/discountColumns'
import { getDiscountTable } from '@/api/discount'
const [submit, reload] = useBaseTable()
//emits
const emits = defineEmits(['delete', 'edit', 'add', 'info'])
const tblProps = ref<any>({
columns: cols,
api: (params: TableInput) => {
return getDiscountTable(params)
}
})
const fetch = () => {
reload()
}
defineExpose({
fetch
})
</script>
<style scoped></style>
@@ -0,0 +1,101 @@
import type { BaseTableColumn } from '@core/type/baseTable'
import { toJalaliNoTime } from '@core/utils/useDataTime'
import { usePrice } from '@core/utils/usePrice'
import CustomTag from '@/components/CustomTag.vue'
export const cols: BaseTableColumn[] = [
{
title: 'ردیف',
dataIndex: 'id',
key: 'id',
filterable: false,
sortable: false,
customRender: (record: any) => {
return record.index + 1
}
},
{
title: 'کد تخفیف',
dataIndex: 'code',
key: 'code',
type: 'Number',
customRender: (record: any) => {
return record.record.code ? (record.record.code) : '-'
}
},
{
title: 'عنوان تخفیف',
dataIndex: 'title',
key: 'title',
type: 'Text',
customRender: (record: any) => {
return record.record.title ? toJalaliNoTime(record.record.title) : '-'
}
},
{
title: 'دفعات قابل استفاده',
dataIndex: 'use_only',
key: 'use_only',
type: 'Number',
customRender: (record: any) => {
return record.record.use_only ? (record.record.use_only) : '-'
}
},
{
title: 'مبلغ تخفیف',
dataIndex: 'discount_price',
key: 'discount_price',
type: 'Text',
customRender: (record: any) => {
return record.record.discount_price ? usePrice(record.record.discount_price) : '-'
}
},
{
title: 'تاریخ شروع',
dataIndex: 'start_at',
key: 'start_at',
type: 'DateTime',
customRender: (record: any) => {
return record.record.start_at ? toJalaliNoTime(record.record.start_at) : '-'
}
},
{
title: 'تاریخ پایان',
dataIndex: 'end_at',
key: 'end_at',
type: 'DateTime',
customRender: (record: any) => {
return record.record.end_at ? toJalaliNoTime(record.record.end_at) : '-'
}
},
{
title: 'وضعیت',
dataIndex: 'is_active',
key: 'is_active',
type: 'Boolean',
customRender: ({ record }) => {
return record.is_active ? (
<div class="flex justify-center">
<CustomTag textColor="#25855A" bgColor="#E3F4E9" class={'font-bold px-6'}>
فعال
</CustomTag>
</div>
) : (
<div class="flex justify-center">
<CustomTag textColor="#C53030" bgColor="#FECACA" class={'font-bold px-6'}>
غیر فعال
</CustomTag>
</div>
)
}
},
{
title: 'عملیات',
dataIndex: 'action',
key: 'action',
slot: 'action',
fixed: 'right',
filterable: false
}
]
+169
View File
@@ -0,0 +1,169 @@
<template>
<div>
<!-- <BasicMainCard>-->
<div class="flex w-full h-full">
<tbl ref="table" class="w-full h-full" @edit="edit" @add="add" />
</div>
<BasicModal
v-model:visible="addDiscountVisible"
width="40rem"
:title="`${editId ? 'ویرایش' : 'افزودن'} تخفیف`"
@ok="ok"
:loading="loading"
@close="addDiscountVisible = false"
>
<a-form :model="form" ref="formRef" autocomplete="off">
<div class="grid md:grid-cols-2 gap-4">
<a-form-item label="عنوان تخفیف" name="title">
<BasicInput v-model:value="form.title" />
</a-form-item>
<a-form-item label="کد تخفیف" name="code">
<BasicInput v-model:value="form.code" />
</a-form-item>
<a-form-item label="دفعات قابل استفاده" name="use_only" :rules="inputRules()">
<BasicInput v-model:value="form.use_only" />
</a-form-item>
<a-form-item label="مبلغ" name="discount_price">
<BasicInput v-model:value="form.discount_price" type="number" />
</a-form-item>
<a-form-item label="تاریخ شروع" name="start_at" :rules="inputRules()">
<BaseDatePicker v-model:value="form.start_at"/>
</a-form-item>
<a-form-item label="تاریخ پایان" name="end_at" :rules="inputRules()">
<BaseDatePicker v-model:value="form.end_at"/>
</a-form-item>
<a-form-item label="وضعیت">
<a-switch v-model:checked="form.is_active" >
<template #checkedChildren>فعال</template>
<template #unCheckedChildren>غیر فعال</template>
</a-switch>
</a-form-item>
</div>
</a-form>
</BasicModal>
</div>
</template>
<script setup lang="ts">
import { inputRules } from '@/utils/inputRules'
import { useStaticApiListsStore } from '@/store/staticApisStore'
import type { Const } from '@/model/const'
import type { User } from '@/model/user'
import { ref } from 'vue'
import tbl from './components/table.vue'
import type { FormInstance } from 'ant-design-vue'
import { message } from 'ant-design-vue/es'
import type { Info } from '@/components/BasicInfoModal/model/Info'
import { cloneDeep } from 'lodash'
import type { Item } from '@/model/Item'
import type { Discount } from '@/model/discount'
import { createDiscount, updateDiscount } from '@/api/discount'
//loading
const loading = ref<boolean>(false)
//define store
const store = useStaticApiListsStore()
//define tbl
const table = ref(null)
const refreshTable = () => table?.value?.fetch()
let updateKey = ref<number>(0)
//form
const form = ref<Discount>({
active: true
})
const formRef = ref<FormInstance>()
//edit
let editId: number | undefined = undefined
async function edit(record: User) {
addDiscountVisible.value = true
editId = record.id
form.value = cloneDeep(record)
}
//add
async function add() {
loading.value = true
editId = undefined
addDiscountVisible.value = true
updateKey.value++
resetData()
loading.value = false
}
//reset data
const resetData = () => {
formRef.value?.resetFields()
form.value = {
code: '',
title: '',
discount_price: undefined,
start_at: undefined,
end_at: undefined,
use_only: undefined,
is_active: false
}
}
//define selects
onMounted(async () => {
loading.value = true
// await getResponsible()
// await getQC()
// await getManager()
loading.value = false
})
interface selectsItem {
responsibleItems: Array<User> | undefined
users: Array<Const> | undefined
}
//add project modal
const addDiscountVisible = ref<boolean>(false)
//submit user
async function ok() {
formRef.value?.validateFields().then(async () => {
// console.log('salam', form.value)
// return
loading.value = true
try {
if (editId) {
if (form.value.password) {
if (form.value.password === form.value.repassword) {
await updateDiscount(editId, form.value)
} else {
message.error('پسورد وارد شده با تکرار پسورد وارد شده یکسان نیست')
return
}
} else {
await updateDiscount(editId, form.value)
}
} else {
await createDiscount(form.value)
}
addDiscountVisible.value = false
refreshTable()
resetData()
message.success('عملیات با موفقیت انجام شد')
// await getResponsible()
// await getQC()
// await getManager()
} catch (e) {
console.error(e)
// message.error('خطا در بارگذاری اطلاعات')
} finally {
loading.value = false
}
})
}
</script>
<style scoped></style>
@@ -10,20 +10,6 @@
</template>--> </template>-->
<template #action="{ column, record }"> <template #action="{ column, record }">
<div class="gap-2 flex justify-center"> <div class="gap-2 flex justify-center">
<!-- <a-tooltip
:key="record.active"
placement="bottom"
class="cursor-pointer"
@click="changeUserActivationFunction(record.id)"
>
<template #title>
<span>{{ record.active ? 'غیرفعال کردن' : 'فعال کردن' }}</span>
</template>
<Icon
:icon="record.active ? 'vuesax-linear:tick-circle' : 'vuesax-linear:close-circle'"
:color="record.active ? '#54AD06' : '#ad0627'"
/>
</a-tooltip>-->
<a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)"> <a-tooltip placement="bottom" class="cursor-pointer" @click="emits('info', record)">
<template #title> <template #title>
<span>مشخصات</span> <span>مشخصات</span>
@@ -36,16 +22,6 @@
</template> </template>
<Icon icon="vuesax-linear:edit" color="#4572E9" /> <Icon icon="vuesax-linear:edit" color="#4572E9" />
</a-tooltip> </a-tooltip>
<!-- <a-tooltip
placement="bottom"
class="cursor-pointer"
@click="emits('delete', record.id)"
>
<template #title>
<span>حذف</span>
</template>
<Icon icon="vuesax-linear:trash" color="#EB3535" />
</a-tooltip>-->
</div> </div>
</template> </template>
</BaseTable> </BaseTable>
+12 -1
View File
@@ -1,5 +1,5 @@
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw } from 'vue-router'
import {getConfigApp} from "@/utils/config";
const Setting: RouteRecordRaw = { const Setting: RouteRecordRaw = {
name: 'settings', name: 'settings',
path: '/settings', path: '/settings',
@@ -61,6 +61,17 @@ const Setting: RouteRecordRaw = {
title: 'هشدار قیمت' title: 'هشدار قیمت'
} }
}, },
{
name: 'discounts',
path: 'discounts',
component: () => import('@/pages/menuPages/discount/index.vue'),
meta: {
permissionsKey: 'discounts',
icon: 'vuesax-linear:notification-bing',
title: 'تخفیفات',
hideMenu: getConfigApp.name !== "goldsun"
}
},
{ {
name: 'configuration', name: 'configuration',
path: 'configuration', path: 'configuration',