Skip to content

Commit 616243a

Browse files
YunaiVgitee-org
authored andcommitted
!83 商品属性模块
Merge pull request !83 from 孔思宇/feat/mall-product-property
2 parents 00c3133 + 1724f2c commit 616243a

File tree

6 files changed

+625
-0
lines changed

6 files changed

+625
-0
lines changed

src/api/mall/product/property.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import request from '@/config/axios'
2+
3+
/**
4+
* 商品属性
5+
*/
6+
export interface PropertyVO {
7+
id?: number
8+
/** 名称 */
9+
name: string
10+
/** 备注 */
11+
remark?: string
12+
}
13+
14+
/**
15+
* 属性值
16+
*/
17+
export interface PropertyValueVO {
18+
id?: number
19+
/** 属性项的编号 */
20+
propertyId?: number
21+
/** 名称 */
22+
name: string
23+
/** 备注 */
24+
remark?: string
25+
}
26+
27+
/**
28+
* 商品属性值的明细
29+
*/
30+
export interface PropertyValueDetailVO {
31+
/** 属性项的编号 */
32+
propertyId: number // 属性的编号
33+
/** 属性的名称 */
34+
propertyName: string
35+
/** 属性值的编号 */
36+
valueId: number
37+
/** 属性值的名称 */
38+
valueName: string
39+
}
40+
41+
// ------------------------ 属性项 -------------------
42+
43+
// 创建属性项
44+
export const createProperty = (data: PropertyVO) => {
45+
return request.post({ url: '/product/property/create', data })
46+
}
47+
48+
// 更新属性项
49+
export const updateProperty = (data: PropertyVO) => {
50+
return request.put({ url: '/product/property/update', data })
51+
}
52+
53+
// 删除属性项
54+
export const deleteProperty = (id: number) => {
55+
return request.delete({ url: `/product/property/delete?id=${id}` })
56+
}
57+
58+
// 获得属性项
59+
export const getProperty = (id: number): Promise<PropertyVO> => {
60+
return request.get({ url: `/product/property/get?id=${id}` })
61+
}
62+
63+
// 获得属性项分页
64+
export const getPropertyPage = (params: PageParam & any) => {
65+
return request.get({ url: '/product/property/page', params })
66+
}
67+
68+
// 获得属性项列表
69+
export const getPropertyList = (params: any) => {
70+
return request.get({ url: '/product/property/list', params })
71+
}
72+
73+
// 获得属性项列表
74+
export const getPropertyListAndValue = (params: any) => {
75+
return request.get({ url: '/product/property/get-value-list', params })
76+
}
77+
78+
// ------------------------ 属性值 -------------------
79+
80+
// 获得属性值分页
81+
export const getPropertyValuePage = (params: PageParam & any) => {
82+
return request.get({ url: '/product/property/value/page', params })
83+
}
84+
85+
// 获得属性值
86+
export const getPropertyValue = (id: number): Promise<PropertyValueVO> => {
87+
return request.get({ url: `/product/property/value/get?id=${id}` })
88+
}
89+
90+
// 创建属性值
91+
export const createPropertyValue = (data: PropertyValueVO) => {
92+
return request.post({ url: '/product/property/value/create', data })
93+
}
94+
95+
// 更新属性值
96+
export const updatePropertyValue = (data: PropertyValueVO) => {
97+
return request.put({ url: '/product/property/value/update', data })
98+
}
99+
100+
// 删除属性值
101+
export const deletePropertyValue = (id: number) => {
102+
return request.delete({ url: `/product/property/value/delete?id=${id}` })
103+
}

src/router/modules/remaining.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,22 @@ const remainingRouter: AppRouteRecordRaw[] = [
319319
}
320320
}
321321
]
322+
},
323+
{
324+
path: '/property',
325+
component: Layout,
326+
name: 'property',
327+
meta: {
328+
hidden: true
329+
},
330+
children: [
331+
{
332+
path: 'value/:propertyId(\\d+)',
333+
component: () => import('@/views/mall/product/property/value/index.vue'),
334+
name: 'PropertyValue',
335+
meta: { title: '商品属性值', icon: '', activeMenu: '/product/property' }
336+
}
337+
]
322338
}
323339
]
324340

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<template>
2+
<Dialog :title="modelTitle" v-model="modelVisible">
3+
<el-form
4+
ref="formRef"
5+
:model="formData"
6+
:rules="formRules"
7+
label-width="80px"
8+
v-loading="formLoading"
9+
>
10+
<el-form-item label="名称" prop="name">
11+
<el-input v-model="formData.name" placeholder="请输入名称" />
12+
</el-form-item>
13+
<el-form-item label="备注" prop="remark">
14+
<el-input v-model="formData.remark" type="textarea" placeholder="请输入内容" />
15+
</el-form-item>
16+
</el-form>
17+
<template #footer>
18+
<div class="dialog-footer">
19+
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
20+
<el-button @click="modelVisible = false">取 消</el-button>
21+
</div>
22+
</template>
23+
</Dialog>
24+
</template>
25+
<script setup lang="ts">
26+
import * as PropertyApi from '@/api/mall/product/property'
27+
28+
const { t } = useI18n() // 国际化
29+
const message = useMessage() // 消息弹窗
30+
31+
const modelVisible = ref(false) // 弹窗的是否展示
32+
const modelTitle = ref('') // 弹窗的标题
33+
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
34+
const formType = ref('') // 表单的类型:create - 新增;update - 修改
35+
const defaultFormData: PropertyApi.PropertyVO = {
36+
id: undefined,
37+
name: ''
38+
}
39+
const formData = ref({ ...defaultFormData })
40+
const formRules = reactive({
41+
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
42+
})
43+
const formRef = ref() // 表单 Ref
44+
45+
/** 打开弹窗 */
46+
const openModal = async (type: string, id?: number) => {
47+
modelVisible.value = true
48+
modelTitle.value = t('action.' + type)
49+
formType.value = type
50+
resetForm()
51+
// 修改时,设置数据
52+
if (id) {
53+
formLoading.value = true
54+
try {
55+
formData.value = await PropertyApi.getProperty(id)
56+
} finally {
57+
formLoading.value = false
58+
}
59+
}
60+
}
61+
defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
62+
63+
/** 提交表单 */
64+
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
65+
const submitForm = async () => {
66+
// 校验表单
67+
if (!formRef) return
68+
const valid = await formRef.value.validate()
69+
if (!valid) return
70+
// 提交请求
71+
formLoading.value = true
72+
try {
73+
const data = formData.value as PropertyApi.PropertyVO
74+
if (formType.value === 'create') {
75+
await PropertyApi.createProperty(data)
76+
message.success(t('common.createSuccess'))
77+
} else {
78+
await PropertyApi.updateProperty(data)
79+
message.success(t('common.updateSuccess'))
80+
}
81+
modelVisible.value = false
82+
// 发送操作成功的事件
83+
emit('success')
84+
} finally {
85+
formLoading.value = false
86+
}
87+
}
88+
89+
/** 重置表单 */
90+
const resetForm = () => {
91+
formData.value = { ...defaultFormData }
92+
formRef.value?.resetFields()
93+
}
94+
</script>
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<template>
2+
<content-wrap>
3+
<!-- 搜索工作栏 -->
4+
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
5+
<el-form-item label="名称" prop="name">
6+
<el-input
7+
v-model="queryParams.name"
8+
placeholder="请输入名称"
9+
clearable
10+
@keyup.enter="handleQuery"
11+
/>
12+
</el-form-item>
13+
<el-form-item label="创建时间" prop="createTime">
14+
<el-date-picker
15+
v-model="queryParams.createTime"
16+
value-format="YYYY-MM-DD HH:mm:ss"
17+
type="daterange"
18+
range-separator="-"
19+
start-placeholder="开始日期"
20+
end-placeholder="结束日期"
21+
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
22+
/>
23+
</el-form-item>
24+
<el-form-item>
25+
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
26+
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
27+
<el-button type="primary" @click="openModal('create')" v-hasPermi="['infra:config:create']">
28+
<Icon icon="ep:plus" class="mr-5px" /> 新增
29+
</el-button>
30+
</el-form-item>
31+
</el-form>
32+
33+
<!-- 列表 -->
34+
<el-table v-loading="loading" :data="list" align="center">
35+
<el-table-column label="编号" align="center" prop="id" />
36+
<el-table-column label="名称" align="center" :show-overflow-tooltip="true">
37+
<template #default="scope">
38+
<router-link :to="'/property/value/' + scope.row.id" class="link-type">
39+
<span>{{ scope.row.name }}</span>
40+
</router-link>
41+
</template>
42+
</el-table-column>
43+
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
44+
<el-table-column
45+
label="创建时间"
46+
align="center"
47+
prop="createTime"
48+
width="180"
49+
:formatter="dateFormatter"
50+
/>
51+
<el-table-column label="操作" align="center">
52+
<template #default="scope">
53+
<el-button
54+
link
55+
type="primary"
56+
@click="openModal('update', scope.row.id)"
57+
v-hasPermi="['infra:config:update']"
58+
>
59+
编辑
60+
</el-button>
61+
<el-button
62+
link
63+
type="danger"
64+
@click="handleDelete(scope.row.id)"
65+
v-hasPermi="['infra:config:delete']"
66+
>
67+
删除
68+
</el-button>
69+
</template>
70+
</el-table-column>
71+
</el-table>
72+
<!-- 分页 -->
73+
<Pagination
74+
:total="total"
75+
v-model:page="queryParams.pageNo"
76+
v-model:limit="queryParams.pageSize"
77+
@pagination="getList"
78+
/>
79+
</content-wrap>
80+
81+
<!-- 表单弹窗:添加/修改 -->
82+
<property-form ref="modalRef" @success="getList" />
83+
</template>
84+
<script setup lang="ts" name="Config">
85+
import { dateFormatter } from '@/utils/formatTime'
86+
import * as PropertyApi from '@/api/mall/product/property'
87+
import PropertyForm from './form.vue'
88+
const message = useMessage() // 消息弹窗
89+
const { t } = useI18n() // 国际化
90+
91+
const loading = ref(true) // 列表的加载中
92+
const total = ref(0) // 列表的总页数
93+
const list = ref([]) // 列表的数据
94+
const queryParams = reactive({
95+
pageNo: 1,
96+
pageSize: 10,
97+
name: undefined,
98+
createTime: []
99+
})
100+
const queryFormRef = ref() // 搜索的表单
101+
102+
/** 查询参数列表 */
103+
const getList = async () => {
104+
loading.value = true
105+
try {
106+
const data = await PropertyApi.getPropertyPage(queryParams)
107+
list.value = data.list
108+
total.value = data.total
109+
} finally {
110+
loading.value = false
111+
}
112+
}
113+
114+
/** 搜索按钮操作 */
115+
const handleQuery = () => {
116+
queryParams.pageNo = 1
117+
getList()
118+
}
119+
120+
/** 重置按钮操作 */
121+
const resetQuery = () => {
122+
queryFormRef.value.resetFields()
123+
handleQuery()
124+
}
125+
126+
/** 添加/修改操作 */
127+
const modalRef = ref()
128+
const openModal = (type: string, id?: number) => {
129+
modalRef.value.openModal(type, id)
130+
}
131+
132+
/** 删除按钮操作 */
133+
const handleDelete = async (id: number) => {
134+
try {
135+
// 删除的二次确认
136+
await message.delConfirm()
137+
// 发起删除
138+
await PropertyApi.deleteProperty(id)
139+
message.success(t('common.delSuccess'))
140+
// 刷新列表
141+
await getList()
142+
} catch {}
143+
}
144+
145+
/** 初始化 **/
146+
onMounted(() => {
147+
getList()
148+
})
149+
</script>

0 commit comments

Comments
 (0)