提交 d9e3bdb7 authored 作者: 袁伟伟's avatar 袁伟伟

feat: 商品价格完成

上级 97cd8e95
......@@ -141,6 +141,7 @@ export interface Goods {
updateTime?: Date;
goodsCategoryList: Array<{ id: number }> | number[];
name: string;
}
export type GoodsPageResult = PageResult<Goods>;
......
import { defHttp } from '/@/utils/http/axios';
const baseApi = '/v1/product/goods-price-distributor-relation';
/**
* 新增
*/
export const add = (data) => defHttp.post({ url: `${baseApi}/`, data: data });
export const search = (params) => defHttp.get({ url: `${baseApi}/search`, params });
export const getById = (id) => defHttp.get({ url: `${baseApi}/${id}` });
export const update = (data) => defHttp.put({ url: `${baseApi}/`, data });
export const remove = (id) => defHttp.delete({ url: `${baseApi}/${id}` });
......@@ -41,3 +41,8 @@
-ms-user-select: none;
user-select: none;
}
p {
padding: 0;
margin: 0;
}
......@@ -43,3 +43,8 @@ svg,
span {
outline: none !important;
}
p {
padding: 0 !important;
margin: 0 !important;
}
......@@ -8,11 +8,13 @@ import { createRouter, createWebHashHistory } from 'vue-router';
export type LayoutMapKey = 'LAYOUT';
const IFRAME = () => import('/@/views/common/iframe/FrameBlank.vue');
const FULLSCREEN = () => import('/@/layouts/page/index.vue');
const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
LayoutMap.set('LAYOUT', LAYOUT);
LayoutMap.set('IFRAME', IFRAME);
LayoutMap.set('FULLSCREEN', FULLSCREEN);
let dynamicViewsModules: Record<string, () => Promise<Recordable>>;
......@@ -40,10 +42,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
});
}
function dynamicImport(
dynamicViewsModules: Record<string, () => Promise<Recordable>>,
component: string,
) {
function dynamicImport(dynamicViewsModules: Record<string, () => Promise<Recordable>>, component: string) {
const keys = Object.keys(dynamicViewsModules);
const matchKeys = keys.filter((key) => {
const k = key.replace('../../views', '');
......@@ -72,7 +71,7 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
routeList.forEach((route) => {
const component = route.component as string;
if (component) {
if (component.toUpperCase() === 'LAYOUT') {
if (component.toUpperCase() === 'LAYOUT' || component.toUpperCase() === 'FULLSCREEN') {
route.component = LayoutMap.get(component.toUpperCase());
} else {
route.children = [cloneDeep(route)];
......@@ -123,11 +122,7 @@ function promoteRouteLevel(routeModule: AppRouteModule) {
}
// Add all sub-routes to the secondary route
function addToChildren(
routes: RouteRecordNormalized[],
children: AppRouteRecordRaw[],
routeModule: AppRouteModule,
) {
function addToChildren(routes: RouteRecordNormalized[], children: AppRouteRecordRaw[], routeModule: AppRouteModule) {
for (let index = 0; index < children.length; index++) {
const child = children[index];
const route = routes.find((item) => item.name === child.name);
......
......@@ -62,6 +62,7 @@
import { DataItem } from '/@/views/product/goods-category/type';
import { GoodsCategory } from '/@/api/model/goodsCategory';
import { fieldNames, rulesRef } from './schema';
import lodash from 'lodash';
const visible = ref<boolean>(false);
const emits = defineEmits(['handleSuccess', 'update:editId']);
......@@ -97,10 +98,9 @@
GoodsCategoryApi.getById(props.editId).then((res) => {
for (const key in formData) {
formData[key] = res[key];
formData.id = res.id;
if (res.lineThirdId) {
formData.lineThirdId = res.lineThirdId * 1;
}
}
if (res.lineThirdId) {
formData.lineThirdId = res.lineThirdId * 1;
}
});
};
......@@ -111,19 +111,20 @@
const handleOk = () => {
formRef.value.validate().then(() => {
if (formData.parentId != 0) {
formData.lineName = undefined;
formData.lineThirdId = undefined;
const data = lodash.cloneDeep(formData);
if (data.parentId != 0) {
data.lineName = undefined;
data.lineThirdId = undefined;
}
let api;
if (props.editId) {
data.id = props.editId;
api = GoodsCategoryApi.update;
} else {
if (formData.id) delete formData.id;
api = GoodsCategoryApi.add;
}
api(formData).then(() => {
api(data).then(() => {
message.success('操作成功');
emits('handleSuccess');
handleCancel();
......
......@@ -14,14 +14,15 @@
<a-form-item label="商品名称" name="goodsName">
<a-input v-model:value="formState.goodsName" />
</a-form-item>
<a-form-item label="产品编号" name="goodsName">
<a-input v-model:value="formState.goodsName" />
<a-form-item label="经销商" name="distributorName">
<a-input v-model:value="formState.distributorName" />
</a-form-item>
<a-form-item label="产品线" name="goodsName">
<a-input v-model:value="formState.goodsName" />
</a-form-item>
<a-form-item label="折扣时间" name="goodsName">
<a-input v-model:value="formState.goodsName" />
<a-form-item label="结束时间" name="discountEndTime">
<a-date-picker
v-model:value="formState.discountEndTimeTo"
:show-time="{ format: 'HH:mm:ss' }"
valueFormat="YYYY-MM-DD HH:mm:ss"
/>
</a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button @click="handleReset">重置</a-button>
......@@ -34,32 +35,76 @@
<span class="title">商品分类</span>
<a-button type="primary" @click="handleAdd">新增</a-button>
</div>
<a-table :dataSource="dataSource" :columns="columns" :pagination="pagination"> </a-table>
<a-table :dataSource="dataSource" :columns="columns" :pagination="pagination" :loading="tableLoading">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<span>{{ record.goodsDto.name }}</span>
</template>
<template v-if="column.key === 'lineName'">
<span>{{ record.goodsDto.lineName }}</span>
</template>
<template v-if="column.key === 'distributor'">
<span>{{ record.distributor.name }}</span>
</template>
<template v-if="column.key === 'time'">
<span>{{ record.discountStartTime + ' - ' + record.discountEndTime }} </span>
</template>
<template v-if="column.key === 'status'">
<span v-if="record.status === 'YES'">启用</span>
<span v-else>禁用</span>
</template>
<template v-if="column.key === 'action'">
<a-button type="link" @click="handleEdit(record.id)">编辑</a-button>
<a-popconfirm
title="是否确认删除?"
ok-text="是"
cancel-text="否"
@confirm="handleDelete(record.id)"
v-if="hasPermission('AUTH_PRODUCT_GOODS_CATEGORY:DELETE')"
>
<a-button type="link">删除</a-button>
</a-popconfirm>
</template>
</template>
</a-table>
</div>
<Modal ref="modalRef" v-model:editId="editId" @handleSuccess="getData"></Modal>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { reactive, ref, onMounted } from 'vue';
import { usePagination } from '/@/hooks/myhooks/index';
import * as GoodsApi from '/@/api/product/goodsApi';
import * as GoodsPriceApi from '/@/api/product/goodsPriceApi';
import { columns } from './schema';
import Modal from './modal.vue';
import { message } from 'ant-design-vue';
import { usePermission } from '/@/hooks/web/usePermission';
const { hasPermission } = usePermission();
const formRef = ref();
const modalRef = ref();
const tableLoading = ref(false);
const formState = reactive<FormState>({
const formState = reactive({
goodsName: undefined,
distributorName: undefined,
discountEndTimeTo: undefined,
});
const dataSource = ref<Goods[]>();
const dataSource = ref();
const editId = ref();
const getData = () => {
GoodsApi.search(Object.assign({ pageSize: pagination.pageSize, pageNum: pagination.current }, formState)).then(
(res) => {
tableLoading.value = true;
GoodsPriceApi.search(Object.assign({ pageSize: pagination.pageSize, pageNum: pagination.current }, formState))
.then((res) => {
pagination.total = res.total;
dataSource.value = res.records;
},
);
})
.finally(() => {
tableLoading.value = false;
});
};
const pagination = usePagination(getData);
......@@ -68,7 +113,24 @@
formRef.value.resetFields();
};
const handleAdd = () => {};
const handleAdd = () => {
modalRef.value.visible = true;
};
const handleEdit = (id) => {
editId.value = id;
handleAdd();
};
const handleDelete = (id) => {
GoodsPriceApi.remove(id).then((res) => {
message.success('删除成功');
getData();
});
};
onMounted(() => {
getData();
});
</script>
<style lang="less" scoped>
......
......@@ -14,27 +14,170 @@
ref="formRef"
:rules="rulesRef"
>
<a-form-item label="产品线" name="name">
<a-input v-model:value="formData.name" />
<a-form-item label="经销商" name="distributorId">
<a-select
v-model:value="formData.distributorId"
style="width: 100%"
placeholder="请选择"
:fieldNames="{ label: 'name', value: 'id' }"
:options="distributorOptions"
></a-select>
</a-form-item>
<a-form-item label="商品" name="name">
<a-input v-model:value="formData.name" />
<a-form-item label="商品" name="goods">
<a-select
v-model:value="formData.goods"
show-search
label-in-value
placeholder="请搜索商品"
style="width: 100%"
:filter-option="false"
:not-found-content="fetching ? undefined : null"
:options="goodsOptions"
@search="fetchGoods"
>
<template v-if="fetching" #notFoundContent>
<a-spin size="small" />
</template>
</a-select>
</a-form-item>
<a-form-item label="折扣时间期限" name="name">
<a-input v-model:value="formData.name" />
<a-form-item label="折扣时间期限" name="time">
<a-range-picker
v-model:value="formData.time"
:show-time="{ format: 'HH:mm:ss' }"
valueFormat="YYYY-MM-DD HH:mm:ss"
:placeholder="['开始时间', '结束时间']"
/>
</a-form-item>
<a-form-item label="折扣设置" name="name">
<a-input v-model:value="formData.name" />
<a-form-item label="折扣设置" name="discountRate">
<a-input-number v-model:value="formData.discountRate" :max="10" :min="0" />
</a-form-item>
<a-form-item label="状态" name="name">
<a-input v-model:value="formData.name" />
<a-form-item label="状态" name="status">
<a-radio-group v-model:value="formData.status">
<a-radio value="YES">启用</a-radio>
<a-radio value="NO">禁用</a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</a-modal>
</template>
<script lang="ts" setup>
import { defineComponent } from 'vue';
import { defineExpose, ref, reactive, defineEmits, watch, defineProps } from 'vue';
import { rulesRef } from './schema';
import { message } from 'ant-design-vue';
import * as GoodsPriceApi from '/@/api/product/goodsPriceApi';
import * as DistributorApi from '/@/api/system/distributorApi';
import * as GoodsApi from '/@/api/product/goodsApi';
import { debounce, cloneDeep } from 'lodash-es';
import { Data } from './type';
const props = defineProps(['editId']);
const emits = defineEmits(['handleSuccess', 'update:editId']);
const formRef = ref<any>();
const visible = ref<boolean>(false);
const formData = reactive<Data>({
distributorId: undefined,
goodsId: undefined,
goods: undefined,
time: <string[]>[],
discountStartTime: '',
discountEndTime: '',
discountRate: 10,
status: 'NO',
id: undefined,
});
const distributorOptions = ref<any>([]);
const goodsOptions = ref();
const getDistributor = () => {
DistributorApi.all().then((res) => {
distributorOptions.value = res;
});
};
let lastFetchId = 0;
const fetching = ref(false);
const fetchGoods = debounce((value) => {
lastFetchId += 1;
const fetchId = lastFetchId;
goodsOptions.value = [];
fetching.value = true;
GoodsApi.search({ pageNum: 1, pageSize: 20, goodsName: value }).then((body) => {
if (fetchId !== lastFetchId) {
return;
}
const data = body.records.map((item) => ({
label: item.name,
value: item.id,
}));
goodsOptions.value = data;
fetching.value = false;
});
}, 300);
const handleOk = () => {
formRef.value.validate().then(() => {
const data = cloneDeep(formData);
data.discountStartTime = data.time[0];
data.discountEndTime = data.time[1];
if (data.goods) {
data.goodsId = data.goods.value;
}
let api;
if (props.editId) {
data.id = props.editId;
api = GoodsPriceApi.update;
} else {
api = GoodsPriceApi.add;
}
api(data).then((res) => {
message.success('操作成功');
emits('handleSuccess');
handleCancel();
});
});
};
const handleCancel = () => {
formRef.value.resetFields();
emits('update:editId', undefined);
visible.value = false;
};
const getEditInfo = () => {
GoodsPriceApi.getById(props.editId).then((res) => {
for (const key in formData) {
formData[key] = res[key];
}
formData.time = [res.discountStartTime, res.discountEndTime];
formData.goods = { value: res.goodsId };
fetchGoods(res.goodsDto.name);
});
};
watch(
() => visible.value,
(n) => {
if (n) {
getDistributor();
}
},
);
watch(
() => props.editId,
(newValue) => {
if (newValue) {
getEditInfo();
}
},
);
defineExpose({ visible });
</script>
<style lang="less" scoped></style>
export const columns = [
{
title: '商品名称',
dataIndex: 'name',
key: 'name',
},
{
title: '产品线',
dataIndex: 'lineName',
key: 'lineName',
},
{
title: '商品名称',
dataIndex: 'name',
key: 'name',
title: '经销商',
dataIndex: 'distributor',
key: 'distributor',
},
{
title: '原价',
dataIndex: 'original',
key: 'original',
dataIndex: 'discountPrice',
key: 'discountPrice',
},
{
title: '折扣',
dataIndex: 'discount',
key: 'discount',
dataIndex: 'discountRate',
key: 'discountRate',
},
{
title: '折扣时间期限',
......@@ -35,3 +40,36 @@ export const columns = [
width: '350px',
},
];
export const rulesRef = {
distributorId: [
{
required: true,
message: '请选择经销商',
},
],
goods: [
{
required: true,
message: '请选择商品',
},
],
time: [
{
required: true,
message: '请选择折扣时间期限',
},
],
discountRate: [
{
required: true,
message: '请设置折扣',
},
],
status: [
{
required: true,
message: '请选择状态',
},
],
};
export interface Data {
distributorId?: string;
goodsId?: string;
goods: { value: string } | undefined;
time: string[];
discountStartTime: string;
discountEndTime: string;
discountRate: number;
status: string;
id?: number;
}
......@@ -35,9 +35,9 @@
<div class="tableWrap">
<div class="titleWrap">
<span class="title">商品分类</span>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-button type="primary" @click="handleAdd(false)">新增</a-button>
</div>
<a-table :dataSource="dataSource" :columns="columns" :pagination="pagination">
<a-table :dataSource="dataSource" :columns="columns" :pagination="pagination" :loading="tableLoading">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<span v-if="record.status === 'YES'"></span>
......@@ -82,6 +82,7 @@
const go = useGo();
const formRef = ref();
const tableLoading = ref(false);
const formState = reactive<FormState>({
goodsName: undefined,
......@@ -96,16 +97,19 @@
const dataSource = ref<Goods[]>();
const getData = () => {
tableLoading.value = true;
const data: any = {};
stateChange.value.forEach((item) => {
data[item] = 'YES';
});
GoodsApi.search(
Object.assign({ pageSize: pagination.pageSize, pageNum: pagination.current }, formState, data),
).then((res) => {
pagination.total = res.total;
dataSource.value = res.records;
});
GoodsApi.search(Object.assign({ pageSize: pagination.pageSize, pageNum: pagination.current }, formState, data))
.then((res) => {
pagination.total = res.total;
dataSource.value = res.records;
})
.finally(() => {
tableLoading.value = false;
});
};
const pagination = usePagination(getData);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论