初始化
This commit is contained in:
37
src/views/MiniMall/Inventory/Comp/InventoryDetail.data.js
Normal file
37
src/views/MiniMall/Inventory/Comp/InventoryDetail.data.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
|
||||
// CrudSchema:https://doc.iocoder.cn/vue3/crud-schema/
|
||||
const crudSchemas = reactive([
|
||||
{
|
||||
label: '产品名称',
|
||||
field: 'name',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '规格名称',
|
||||
field: 'specsName',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '仓库',
|
||||
field: 'warehouse',
|
||||
isSearch: true,
|
||||
isTable: true,
|
||||
search: {
|
||||
component: 'Select',
|
||||
api: () => [
|
||||
{ label: '自营仓', value: 1 },
|
||||
{ label: '供应商仓', value: 2 }
|
||||
],
|
||||
componentProps: {
|
||||
optionsAlias: {
|
||||
labelField: 'label',
|
||||
valueField: 'value'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
export const { allSchemas } = useCrudSchemas(crudSchemas)
|
||||
60
src/views/MiniMall/Inventory/Comp/InventoryDetail.vue
Normal file
60
src/views/MiniMall/Inventory/Comp/InventoryDetail.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 搜索工作栏 -->
|
||||
<Search
|
||||
:schema="allSchemas.searchSchema"
|
||||
labelWidth="0"
|
||||
expand
|
||||
expand-field="name"
|
||||
@search="setSearchParams"
|
||||
@reset="setSearchParams"
|
||||
/>
|
||||
<!-- 列表 -->
|
||||
<SSTable
|
||||
class="mt-20px"
|
||||
v-model:tableObject="tableObject"
|
||||
:tableColumns="allSchemas.tableColumns"
|
||||
@get-list="getTableList"
|
||||
>
|
||||
<el-table-column
|
||||
v-for="item in allSchemas.tableColumns"
|
||||
:key="item.table?.field || item.field"
|
||||
:prop="item.table?.field || item.field"
|
||||
:label="item.label"
|
||||
:fixed="item.fixed"
|
||||
min-width="150px"
|
||||
showOverflowTooltip
|
||||
/>
|
||||
<el-table-column prop="count" label="库存数量">
|
||||
<!-- <template #default="{ row }">
|
||||
<el-button v-if="row.count" type="primary" text @click="handleDetail">{{
|
||||
row.count
|
||||
}}</el-button>
|
||||
<span v-else>{{ row.count }}</span>
|
||||
</template> -->
|
||||
</el-table-column>
|
||||
</SSTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { allSchemas } from './InventoryDetail.data.js'
|
||||
|
||||
const tableObject = ref({
|
||||
tableList: [],
|
||||
loading: false,
|
||||
total: 1,
|
||||
pageSize: 20,
|
||||
currentPage: 1
|
||||
})
|
||||
|
||||
function setSearchParams() {
|
||||
tableObject.value.tableList = []
|
||||
}
|
||||
|
||||
function getTableList() {
|
||||
tableObject.value.tableList = []
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
90
src/views/MiniMall/Inventory/Comp/InventoryRecord.vue
Normal file
90
src/views/MiniMall/Inventory/Comp/InventoryRecord.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div>
|
||||
<Search
|
||||
:schema="allSchemas.searchSchema"
|
||||
labelWidth="0"
|
||||
@search="setSearchParams"
|
||||
@reset="setSearchParams"
|
||||
/>
|
||||
|
||||
<el-table class="mt-20px" :data="tableList" border>
|
||||
<el-table-column type="index" width="50px" />
|
||||
<el-table-column prop="" label="产品名称" />
|
||||
<el-table-column prop="" label="规格" />
|
||||
<el-table-column prop="" label="变动类型" />
|
||||
<el-table-column prop="" label="数量" />
|
||||
<el-table-column prop="" label="金额" />
|
||||
<el-table-column prop="" label="变动时间" />
|
||||
<el-table-column prop="" label="变动人员" />
|
||||
<el-table-column prop="" label="所属仓库" />
|
||||
<el-table-column prop="" label="备注" />
|
||||
</el-table>
|
||||
<Pagination
|
||||
v-model:limit="searchForm.pageSize"
|
||||
v-model:page="searchForm.currentPage"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const crudSchemas = ref([
|
||||
{
|
||||
label: '仓库名称',
|
||||
field: 'warehouse',
|
||||
isSearch: true,
|
||||
search: {
|
||||
component: 'Select',
|
||||
api: () => [
|
||||
{ label: '自营仓', value: 1 },
|
||||
{ label: '供应商仓', value: 2 }
|
||||
],
|
||||
componentProps: {
|
||||
optionsAlias: {
|
||||
labelField: 'label',
|
||||
valueField: 'value'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '变动类型',
|
||||
field: 'type',
|
||||
isSearch: true,
|
||||
search: {
|
||||
component: 'Select',
|
||||
api: () => [
|
||||
{ label: '入库', value: 1 },
|
||||
{ label: '出库', value: 2 },
|
||||
{ label: '售后', value: 3 }
|
||||
],
|
||||
componentProps: {
|
||||
optionsAlias: {
|
||||
labelField: 'label',
|
||||
valueField: 'value'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
const { allSchemas } = useCrudSchemas(crudSchemas.value)
|
||||
|
||||
const searchForm = ref({
|
||||
pageSize: 20,
|
||||
currentPage: 1
|
||||
})
|
||||
|
||||
const tableList = ref([])
|
||||
const total = ref(0)
|
||||
|
||||
function getList() {
|
||||
tableList.value = []
|
||||
}
|
||||
|
||||
function setSearchParams() {
|
||||
tableList.value = []
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
75
src/views/MiniMall/Inventory/Comp/Warehouse.vue
Normal file
75
src/views/MiniMall/Inventory/Comp/Warehouse.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 搜索工作栏 -->
|
||||
<Search
|
||||
:schema="allSchemas.searchSchema"
|
||||
labelWidth="0"
|
||||
@search="setSearchParams"
|
||||
@reset="setSearchParams"
|
||||
/>
|
||||
<!-- 列表 -->
|
||||
<SSTable
|
||||
class="mt-20px"
|
||||
v-model:tableObject="tableObject"
|
||||
:tableColumns="allSchemas.tableColumns"
|
||||
@get-list="getTableList"
|
||||
>
|
||||
<el-table-column type="index" width="80px" />
|
||||
<el-table-column
|
||||
v-for="item in allSchemas.tableColumns"
|
||||
:key="item.field"
|
||||
:prop="item.field"
|
||||
:label="item.label"
|
||||
/>
|
||||
<el-table-column label="操作" width="200px">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" text :disabled="row.default">修改</el-button>
|
||||
<el-button type="danger" text :disabled="row.default" @click="remove(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</SSTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const crudSchemas = ref([
|
||||
{
|
||||
label: '仓库名称',
|
||||
field: 'name',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
}
|
||||
])
|
||||
|
||||
const { allSchemas } = useCrudSchemas(crudSchemas.value)
|
||||
|
||||
const tableObject = ref({
|
||||
tableList: [],
|
||||
loading: false,
|
||||
total: 1,
|
||||
pageSize: 20,
|
||||
currentPage: 1
|
||||
})
|
||||
|
||||
function setSearchParams() {
|
||||
tableObject.value.tableList = [
|
||||
{ name: '自营仓', default: true },
|
||||
{ name: '供应商仓', default: true }
|
||||
]
|
||||
}
|
||||
|
||||
function getTableList() {
|
||||
tableObject.value.tableList = [
|
||||
{ name: '自营仓', default: true },
|
||||
{ name: '供应商仓', default: true }
|
||||
]
|
||||
}
|
||||
|
||||
function remove(row) {
|
||||
console.log(row)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
23
src/views/MiniMall/Inventory/index.vue
Normal file
23
src/views/MiniMall/Inventory/index.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<el-tabs v-model="curTab" type="card" tab-position="top">
|
||||
<el-tab-pane label="库存" name="1">
|
||||
<InventoryDetail v-if="curTab == 1" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="库存变动记录" name="2">
|
||||
<InventoryRecord v-if="curTab == 2" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="仓库" name="3">
|
||||
<Warehouse v-if="curTab == 3" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import InventoryDetail from './Comp/InventoryDetail.vue'
|
||||
import Warehouse from './Comp/Warehouse.vue'
|
||||
import InventoryRecord from './Comp/InventoryRecord.vue'
|
||||
|
||||
const curTab = ref('1')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
122
src/views/MiniMall/MallSet/Comp/FieldProduct.vue
Normal file
122
src/views/MiniMall/MallSet/Comp/FieldProduct.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<el-row :gutter="80">
|
||||
<el-col :span="10" :offset="0">
|
||||
<el-button class="mb-10px" type="primary" @click="handleInsert">新增属性</el-button>
|
||||
<el-table :data="tableList">
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column label="启用状态">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
:disabled="!row.canUpdate"
|
||||
@change="changeStatus(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
:disabled="!row.canUpdate"
|
||||
style="padding: 0"
|
||||
@click="remove(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
<el-col :span="14" :offset="0">
|
||||
<el-form :model="form" ref="fieldForm" :rules="rules" label-width="80px" :inline="false">
|
||||
<el-form-item label="属性名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入属性名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="属性类型" prop="type">
|
||||
<el-select
|
||||
v-model="form.type"
|
||||
placeholder="请选择属性类型"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in typeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="['Checkbox', 'Radio', 'Select'].includes(form.type)"
|
||||
label="选项"
|
||||
prop="option"
|
||||
key="option"
|
||||
>
|
||||
<div>
|
||||
<el-button type="primary" @click="optionList.push([])"> 新增选项 </el-button>
|
||||
<div
|
||||
class="flex justify-between mt-10px"
|
||||
v-for="(item, index) in optionList"
|
||||
:key="index"
|
||||
>
|
||||
<el-input v-model="item.label" placeholder="请输入选项内容" clearable />
|
||||
<el-button type="primary" text @click="optionList.splice(index, 1)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const tableList = ref([{ name: '单位', status: 0, canUpdate: true }])
|
||||
|
||||
const form = ref({
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
option: undefined
|
||||
})
|
||||
|
||||
const typeOptions = ref([
|
||||
{ label: '输入框', value: 'Input' },
|
||||
{ label: '多选', value: 'Checkbox' },
|
||||
{ label: '单选', value: 'Radio' },
|
||||
{ label: '下拉选', value: 'Select' },
|
||||
{ label: '开关', value: 'Switch' },
|
||||
{ label: '日期选择', value: 'DatePicker' },
|
||||
{ label: '时间选择', value: 'TimePicker' },
|
||||
{ label: '富文本', value: 'Editor' },
|
||||
{ label: '图片', value: 'UploadImg' },
|
||||
{ label: '文件', value: 'UploadFile' }
|
||||
])
|
||||
|
||||
const rules = {}
|
||||
|
||||
const optionList = ref([])
|
||||
|
||||
function handleInsert() {
|
||||
console.log('新增')
|
||||
}
|
||||
|
||||
function changeStatus(row) {
|
||||
console.log(row.status)
|
||||
}
|
||||
|
||||
function remove(row) {
|
||||
console.log(row.status)
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
console.log('保存')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
204
src/views/MiniMall/MallSet/Comp/MsgSend.vue
Normal file
204
src/views/MiniMall/MallSet/Comp/MsgSend.vue
Normal file
@@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<el-card shadow="always" :body-style="{ padding: '10px' }">
|
||||
<div
|
||||
class="flex text-14px cursor-pointer"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
style="height: 48px; line-height: 48px; width: 240px"
|
||||
@click="handleChoose(item.value)"
|
||||
:class="{ actived: item.value == msgType }"
|
||||
>
|
||||
<div class="font-bold pl-20px">{{ item.name }}</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="always" :body-style="{ padding: '10px' }" class="ml-20px flex-1">
|
||||
<el-form :model="form" ref="msgForm" :rules="rules" label-width="100px" :inline="false">
|
||||
<el-form-item prop="isEnable">
|
||||
<template #label>
|
||||
<div class="flex justify-center" style="align-items: center">
|
||||
<Tooltip message="是否发送对应消息通知" />
|
||||
<span>是否启用</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-radio-group v-model="form.isEnable">
|
||||
<el-radio :label="1"> 启用 </el-radio>
|
||||
<el-radio :label="0"> 禁用 </el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="form.isEnable">
|
||||
<el-form-item label="微信通知" prop="wxMsg">
|
||||
<el-radio-group v-model="form.wxMsg">
|
||||
<el-radio :label="1"> 启用 </el-radio>
|
||||
<el-radio :label="0"> 禁用 </el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="发送对象" prop="msgTo">
|
||||
<div>
|
||||
<el-checkbox-group v-model="form.msgTo">
|
||||
<el-checkbox :label="1"> 创建人 </el-checkbox>
|
||||
<el-checkbox :label="2"> 申请人 </el-checkbox>
|
||||
<el-checkbox :label="3"> 指定用户 </el-checkbox>
|
||||
<el-checkbox v-if="form.wxMsg" :label="4"> 微信群 </el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<div class="flex">
|
||||
<div v-if="form.msgTo.includes(3)" class="flex mr-20px" style="align-items: center">
|
||||
<div class="mr-15px" style="width: 80px">指定用户:</div>
|
||||
<el-select
|
||||
v-model="form.msgToUsers"
|
||||
placeholder="选择用户,可多选"
|
||||
filterable
|
||||
multiple
|
||||
style="width: 300px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div v-if="form.msgTo.includes(4)" class="flex mr-20px" style="align-items: center">
|
||||
<div
|
||||
class="mr-15px flex"
|
||||
style="align-items: center; width: 180px; text-align: right"
|
||||
>
|
||||
<Tooltip message="已添加微信机器人的群" />
|
||||
<span>微信群名称:</span>
|
||||
</div>
|
||||
<el-input v-model="form.wxGroup" placeholder="请输入群名称" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="发送时间" prop="sendTime">
|
||||
<div>
|
||||
<el-radio-group v-model="form.sendTime">
|
||||
<el-radio :label="1"> 立即发送 </el-radio>
|
||||
<el-radio :label="2"> 指定时间 </el-radio>
|
||||
</el-radio-group>
|
||||
<div v-if="form.sendTime == 2">
|
||||
<span class="mr-15px">指定时间:</span>
|
||||
<el-radio-group v-model="form.msgTimeType" @change="form.days = []">
|
||||
<el-radio :label="1"> 每日 </el-radio>
|
||||
<el-radio :label="2"> 次日 </el-radio>
|
||||
<el-radio :label="3"> 每周 </el-radio>
|
||||
<el-radio :label="4"> 每月 </el-radio>
|
||||
</el-radio-group>
|
||||
<div v-if="[3, 4].includes(form.msgTimeType)" class="mt-15px">
|
||||
<span class="mr-15px">日期:</span>
|
||||
<el-select v-model="form.days" placeholder="选择日期,可多选" multiple filterable>
|
||||
<el-option
|
||||
v-for="item in dayOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="mt-15px">
|
||||
<span class="mr-15px">具体时间:</span>
|
||||
<el-time-picker
|
||||
v-model="form.msgTime"
|
||||
placeholder="具体时间"
|
||||
:clearable="false"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
class="ml-20px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="消息模板" prop="msgTemplate">
|
||||
<el-input
|
||||
v-model="form.msgTemplate"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
placeholder="请输入模板内容"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<template #label>
|
||||
<div class="flex justify-center" style="align-items: center">
|
||||
<Tooltip message="当库存达到多少时,发送预警消息" />
|
||||
<span>预警阈值</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-input-number v-model="form.limit" :min="1" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button>重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const list = [
|
||||
{ name: '库存预警通知', value: 'KCYJTZ' },
|
||||
{ name: '采购申请通知', value: 'CGSQTZ' },
|
||||
{ name: '审核结果通知', value: 'CGSHJGTZ' }
|
||||
]
|
||||
|
||||
const msgType = ref('KCYJTZ')
|
||||
|
||||
const form = ref({
|
||||
isEnable: true,
|
||||
wxMsg: false,
|
||||
msgTo: [],
|
||||
msgToUsers: [],
|
||||
wxGroup: '',
|
||||
sendTime: 1,
|
||||
msgTimeType: 1,
|
||||
msgTime: '00:00',
|
||||
|
||||
days: []
|
||||
})
|
||||
const rules = ref({})
|
||||
const userOptions = ref([
|
||||
{ label: '张张', value: '1' },
|
||||
{ label: '李李', value: '2' },
|
||||
{ label: '王王', value: '3' },
|
||||
{ label: '赵赵', value: '4' }
|
||||
])
|
||||
|
||||
const dayOptions = computed(() => {
|
||||
const weekList = [
|
||||
{ label: '周一', value: 1 },
|
||||
{ label: '周二', value: 2 },
|
||||
{ label: '周三', value: 3 },
|
||||
{ label: '周四', value: 4 },
|
||||
{ label: '周五', value: 5 },
|
||||
{ label: '周六', value: 6 },
|
||||
{ label: '周日', value: 7 }
|
||||
]
|
||||
let monthList = []
|
||||
for (let i = 0; i < 28; i++) {
|
||||
monthList.push({ label: `${i + 1}日`, value: i + 1 })
|
||||
}
|
||||
let obj = {
|
||||
3: weekList,
|
||||
4: monthList
|
||||
}
|
||||
return obj[form.value.msgTimeType] || []
|
||||
})
|
||||
|
||||
function handleChoose(type) {
|
||||
msgType.value = type
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
console.log('保存成功')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.actived {
|
||||
background-color: #f0f7ff;
|
||||
}
|
||||
</style>
|
||||
19
src/views/MiniMall/MallSet/index.vue
Normal file
19
src/views/MiniMall/MallSet/index.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<el-tabs v-model="tabIndex" type="border-card">
|
||||
<el-tab-pane label="产品属性" :name="0">
|
||||
<FieldProduct />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="消息通知" :name="9">
|
||||
<MsgSend />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import FieldProduct from './Comp/FieldProduct.vue'
|
||||
import MsgSend from './Comp/MsgSend.vue'
|
||||
|
||||
const tabIndex = ref(0)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
98
src/views/MiniMall/Product/Comp/ProductAttributesAddForm.vue
Normal file
98
src/views/MiniMall/Product/Comp/ProductAttributesAddForm.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="属性名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" name="ProductPropertyForm" setup>
|
||||
import * as PropertyApi from '@/api/mall/product/property'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('添加商品属性') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formData = ref({
|
||||
name: ''
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const attributeList = ref([]) // 商品属性列表
|
||||
const props = defineProps({
|
||||
propertyList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.propertyList,
|
||||
(data) => {
|
||||
if (!data) return
|
||||
attributeList.value = data
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
/** 打开弹窗 */
|
||||
const open = async () => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as PropertyApi.PropertyVO
|
||||
// 检查属性是否已存在,如果有则返回属性和其下属性值
|
||||
const res = await PropertyApi.getPropertyListAndValue({ name: data.name })
|
||||
if (res.length === 0) {
|
||||
const propertyId = await PropertyApi.createProperty(data)
|
||||
attributeList.value.push({ id: propertyId, ...formData.value, values: [] })
|
||||
} else {
|
||||
if (res[0].values === null) {
|
||||
res[0].values = []
|
||||
}
|
||||
attributeList.value.push(res[0]) // 因为只用一个
|
||||
}
|
||||
message.success(t('common.createSuccess'))
|
||||
dialogVisible.value = false
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
name: '',
|
||||
remark: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
317
src/views/MiniMall/Product/Comp/SkuList.vue
Normal file
317
src/views/MiniMall/Product/Comp/SkuList.vue
Normal file
@@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<el-table
|
||||
:data="isBatch ? skuList : formData.skus"
|
||||
border
|
||||
class="tabNumWidth"
|
||||
max-height="500"
|
||||
size="small"
|
||||
>
|
||||
<el-table-column align="center" fixed="left" label="图片" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<UploadImg v-model="row.picUrl" height="80px" width="100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="formData.specType && !isBatch">
|
||||
<!-- 根据商品属性动态添加 -->
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableHeaders"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
align="center"
|
||||
min-width="120"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<!-- TODO puhui999:展示成蓝色,有点区分度哈 -->
|
||||
{{ row.properties[index]?.valueName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column align="center" label="商品条码" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.barCode" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="销售价(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.price" :min="0" :precision="2" :step="0.1" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="市场价(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.marketPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="成本价(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.costPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="库存" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.stock" :min="0" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="重量(kg)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.weight" :min="0" :precision="2" :step="0.1" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="体积(m^3)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.volume" :min="0" :precision="2" :step="0.1" class="w-100%" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="formData.subCommissionType">
|
||||
<el-table-column align="center" label="一级返佣(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.subCommissionFirstPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二级返佣(元)" min-width="168">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.subCommissionSecondPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:step="0.1"
|
||||
class="w-100%"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column v-if="formData.specType" align="center" fixed="right" label="操作" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="isBatch" link size="small" type="primary" @click="batchAdd">
|
||||
批量添加
|
||||
</el-button>
|
||||
<el-button v-else link size="small" type="primary" @click="deleteSku(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<script lang="ts" name="SkuList" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { UploadImg } from '@/components/UploadFile'
|
||||
import type { Property, SkuType, SpuType } from '@/api/mall/product/spu'
|
||||
|
||||
const props = defineProps({
|
||||
propFormData: {
|
||||
type: Object as PropType<SpuType>,
|
||||
default: () => {}
|
||||
},
|
||||
propertyList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
isBatch: propTypes.bool.def(false) // 是否作为批量操作组件
|
||||
})
|
||||
const formData = ref<SpuType>() // 表单数据
|
||||
const skuList = ref<SkuType[]>([
|
||||
{
|
||||
price: 0, // 商品价格
|
||||
marketPrice: 0, // 市场价
|
||||
costPrice: 0, // 成本价
|
||||
barCode: '', // 商品条码
|
||||
picUrl: '', // 图片地址
|
||||
stock: 0, // 库存
|
||||
weight: 0, // 商品重量
|
||||
volume: 0, // 商品体积
|
||||
subCommissionFirstPrice: 0, // 一级分销的佣金
|
||||
subCommissionSecondPrice: 0 // 二级分销的佣金
|
||||
}
|
||||
]) // 批量添加时的临时数据
|
||||
// TODO @puhui999:保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。
|
||||
|
||||
/** 批量添加 */
|
||||
const batchAdd = () => {
|
||||
formData.value.skus.forEach((item) => {
|
||||
copyValueToTarget(item, skuList.value[0])
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除 sku */
|
||||
const deleteSku = (row) => {
|
||||
const index = formData.value.skus.findIndex(
|
||||
// 直接把列表转成字符串比较
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
formData.value.skus.splice(index, 1)
|
||||
}
|
||||
const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表头
|
||||
|
||||
/**
|
||||
* 将传进来的值赋值给 skuList
|
||||
*/
|
||||
watch(
|
||||
() => props.propFormData,
|
||||
(data) => {
|
||||
if (!data) return
|
||||
formData.value = data
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
/** 生成表数据 */
|
||||
const generateTableData = (propertyList: any[]) => {
|
||||
// 构建数据结构
|
||||
const propertyValues = propertyList.map((item) =>
|
||||
item.values.map((v) => ({
|
||||
propertyId: item.id,
|
||||
propertyName: item.name,
|
||||
valueId: v.id,
|
||||
valueName: v.name
|
||||
}))
|
||||
)
|
||||
// TODO @puhui:是不是 buildSkuList,这样容易理解一点哈。item 改成 sku
|
||||
const buildList = build(propertyValues)
|
||||
// 如果回显的 sku 属性和添加的属性不一致则重置 skus 列表
|
||||
if (!validateData(propertyList)) {
|
||||
// 如果不一致则重置表数据,默认添加新的属性重新生成 sku 列表
|
||||
formData.value!.skus = []
|
||||
}
|
||||
for (const item of buildList) {
|
||||
const row = {
|
||||
properties: Array.isArray(item) ? item : [item], // 如果只有一个属性的话返回的是一个 property 对象
|
||||
price: 0,
|
||||
marketPrice: 0,
|
||||
costPrice: 0,
|
||||
barCode: '',
|
||||
picUrl: '',
|
||||
stock: 0,
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
subCommissionFirstPrice: 0,
|
||||
subCommissionSecondPrice: 0
|
||||
}
|
||||
// 如果存在属性相同的 sku 则不做处理
|
||||
const index = formData.value!.skus.findIndex(
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
if (index !== -1) {
|
||||
continue
|
||||
}
|
||||
formData.value.skus.push(row)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 skus 前置校验
|
||||
*/
|
||||
const validateData = (propertyList: any[]) => {
|
||||
const skuPropertyIds = []
|
||||
formData.value.skus.forEach((sku) =>
|
||||
sku.properties
|
||||
?.map((property) => property.propertyId)
|
||||
.forEach((propertyId) => {
|
||||
if (skuPropertyIds.indexOf(propertyId) === -1) {
|
||||
skuPropertyIds.push(propertyId)
|
||||
}
|
||||
})
|
||||
)
|
||||
const propertyIds = propertyList.map((item) => item.id)
|
||||
return skuPropertyIds.length === propertyIds.length
|
||||
}
|
||||
|
||||
/** 构建所有排列组合 */
|
||||
const build = (propertyValuesList: Property[][]) => {
|
||||
if (propertyValuesList.length === 0) {
|
||||
return []
|
||||
} else if (propertyValuesList.length === 1) {
|
||||
return propertyValuesList[0]
|
||||
} else {
|
||||
const result: Property[][] = []
|
||||
const rest = build(propertyValuesList.slice(1))
|
||||
for (let i = 0; i < propertyValuesList[0].length; i++) {
|
||||
for (let j = 0; j < rest.length; j++) {
|
||||
// 第一次不是数组结构,后面的都是数组结构
|
||||
if (Array.isArray(rest[j])) {
|
||||
result.push([propertyValuesList[0][i], ...rest[j]])
|
||||
} else {
|
||||
result.push([propertyValuesList[0][i], rest[j]])
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听属性列表,生成相关参数和表头 */
|
||||
watch(
|
||||
() => props.propertyList,
|
||||
(propertyList) => {
|
||||
// 如果不是多规格则结束
|
||||
if (!formData.value.specType) {
|
||||
return
|
||||
}
|
||||
// 如果当前组件作为批量添加数据使用,则重置表数据
|
||||
if (props.isBatch) {
|
||||
skuList.value = [
|
||||
{
|
||||
price: 0,
|
||||
marketPrice: 0,
|
||||
costPrice: 0,
|
||||
barCode: '',
|
||||
picUrl: '',
|
||||
stock: 0,
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
subCommissionFirstPrice: 0,
|
||||
subCommissionSecondPrice: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// 判断代理对象是否为空
|
||||
if (JSON.stringify(propertyList) === '[]') {
|
||||
return
|
||||
}
|
||||
// 重置表头
|
||||
tableHeaders.value = []
|
||||
// 生成表头
|
||||
propertyList.forEach((item, index) => {
|
||||
// name加属性项index区分属性值
|
||||
tableHeaders.value.push({ prop: `name${index}`, label: item.name })
|
||||
})
|
||||
|
||||
// 如果回显的 sku 属性和添加的属性一致则不处理
|
||||
if (validateData(propertyList)) {
|
||||
return
|
||||
}
|
||||
// 添加新属性没有属性值也不做处理
|
||||
if (propertyList.some((item) => item.values.length === 0)) {
|
||||
return
|
||||
}
|
||||
// 生成 table 数据,即 sku 列表
|
||||
generateTableData(propertyList)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
// 暴露出生成 sku 方法,给添加属性成功时调用
|
||||
defineExpose({ generateTableData })
|
||||
</script>
|
||||
252
src/views/MiniMall/Product/add.vue
Normal file
252
src/views/MiniMall/Product/add.vue
Normal file
@@ -0,0 +1,252 @@
|
||||
<template>
|
||||
<el-tabs v-model="tabName" type="border-card" tab-position="top">
|
||||
<el-tab-pane label="商品信息" name="basic">
|
||||
<el-form :model="form" ref="spuForm" :rules="rules" label-width="90px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8" :offset="0">
|
||||
<el-form-item label="产品名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入产品名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" :offset="0">
|
||||
<el-form-item label="分类" prop="category">
|
||||
<el-input v-model="form.category" placeholder="请输入分类" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" :offset="0">
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input v-model="form.brand" placeholder="请输入品牌" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="产品简介" prop="intro">
|
||||
<el-input
|
||||
v-model="form.intro"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4 }"
|
||||
placeholder="请输入产品简介"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="主图" prop="picUrl">
|
||||
<UploadImg v-model="form.picUrl" height="100px" width="100px" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="轮播图" prop="sliderPicUrls">
|
||||
<UploadImgs v-model:modelValue="form.sliderPicUrls" height="100px" width="100px" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="商品规格">
|
||||
<el-button @click="handleAddSpec">添加规格</el-button>
|
||||
<el-col v-for="(item, index) in form.specsList" :key="index">
|
||||
<div>
|
||||
<el-text class="mx-1">属性名:</el-text>
|
||||
<el-tag class="mx-1" closable type="success" @close="handleCloseProperty(index)"
|
||||
>{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<el-text class="mx-1">属性值:</el-text>
|
||||
<el-tag
|
||||
v-for="(value, valueIndex) in item.values"
|
||||
:key="value.id"
|
||||
class="mx-1"
|
||||
closable
|
||||
@close="handleCloseValue(index, valueIndex)"
|
||||
>
|
||||
{{ value.name }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
v-show="inputVisible(index)"
|
||||
:id="`input${index}`"
|
||||
:ref="setInputRef"
|
||||
v-model="inputValue"
|
||||
class="!w-20"
|
||||
size="small"
|
||||
@blur="handleInputConfirm(index, item.id)"
|
||||
@keyup.enter="handleInputConfirm(index, item.id)"
|
||||
/>
|
||||
<el-button
|
||||
v-show="!inputVisible(index)"
|
||||
class="button-new-tag ml-1"
|
||||
size="small"
|
||||
@click="showInput(index)"
|
||||
>
|
||||
+ 添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-divider class="my-10px" />
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-table :data="form.skuList">
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="specsName" label="规格名称">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.specsName" placeholder="请输入" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="col in form.specsList"
|
||||
:prop="col.id"
|
||||
:key="col.id"
|
||||
:label="col.name"
|
||||
/>
|
||||
<el-table-column prop="price" label="销售价">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.price" :min="0.01" :step="1" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="intro" label="简介">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.intro" placeholder="请输入简介" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="mt-20px flex justify-center">
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button plain>重置</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="详细信息" name="detail">
|
||||
<Editor v-model:modelValue="form.description" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<ProductAttributesAddForm ref="attributesAddFormRef" :propertyList="form.specsList" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ProductAttributesAddForm from './Comp/ProductAttributesAddForm.vue'
|
||||
const route = useRoute()
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const tabName = ref('basic')
|
||||
const form = ref({
|
||||
name: '',
|
||||
category: '',
|
||||
brand: '',
|
||||
intro: '',
|
||||
picUrl: '',
|
||||
sliderPicUrls: [],
|
||||
specsList: [],
|
||||
skuList: [],
|
||||
description: null
|
||||
})
|
||||
const rules = ref({})
|
||||
const attributesAddFormRef = ref() // 添加商品属性表单
|
||||
|
||||
/** 删除属性*/
|
||||
function handleCloseProperty(index) {
|
||||
form.value.specsList?.splice(index, 1)
|
||||
}
|
||||
|
||||
const attributeIndex = ref(null)
|
||||
// 输入框显隐控制
|
||||
const inputVisible = computed(() => (index) => {
|
||||
if (attributeIndex.value === null) return false
|
||||
if (attributeIndex.value === index) return true
|
||||
})
|
||||
|
||||
const inputValue = ref('') // 输入框值
|
||||
/** 输入框失去焦点或点击回车时触发 */
|
||||
async function handleInputConfirm(index, propertyId) {
|
||||
if (inputValue.value) {
|
||||
// 保存属性值
|
||||
try {
|
||||
// const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value })
|
||||
const id = propertyId || parseInt(Math.random() * 1000000)
|
||||
form.value.specsList[index].values.push({ id, name: inputValue.value })
|
||||
message.success('添加成功')
|
||||
} catch {
|
||||
message.error('添加失败,请重试')
|
||||
}
|
||||
}
|
||||
attributeIndex.value = null
|
||||
inputValue.value = ''
|
||||
form.value.skuList = getTableList()
|
||||
}
|
||||
|
||||
function getTableList() {
|
||||
let list = []
|
||||
form.value.specsList.map((item) => {
|
||||
if (!list.length) {
|
||||
item.values.map((it) => {
|
||||
const obj = {}
|
||||
obj[it.id] = it.name
|
||||
list.push(obj)
|
||||
})
|
||||
} else {
|
||||
item.values.map((it, index) => {
|
||||
if (index < list.length) {
|
||||
list[index][it.id] = it.name
|
||||
} else {
|
||||
const obj = {}
|
||||
obj[it.id] = it.name
|
||||
list.push(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
const inputRef = ref([]) //标签输入框Ref
|
||||
/** 显示输入框并获取焦点 */
|
||||
const showInput = async (index) => {
|
||||
attributeIndex.value = index
|
||||
inputRef.value[index].focus()
|
||||
}
|
||||
|
||||
/** 解决 ref 在 v-for 中的获取问题*/
|
||||
const setInputRef = (el) => {
|
||||
if (el === null || typeof el === 'undefined') return
|
||||
// 如果不存在id相同的元素才添加
|
||||
if (!inputRef.value.some((item) => item.input?.attributes.id === el.input?.attributes.id)) {
|
||||
inputRef.value.push(el)
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddSpec() {
|
||||
const id = parseInt(Math.random() * 1000)
|
||||
form.value.specsList.push({ name: `测试规格${id}`, id, values: [] })
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
message.success('保存成功!')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (route.query?.id) {
|
||||
form.value = {
|
||||
name: '商品名称哦~'
|
||||
}
|
||||
} else {
|
||||
form.value = {
|
||||
name: '',
|
||||
category: '',
|
||||
brand: '',
|
||||
intro: '',
|
||||
picUrl: '',
|
||||
sliderPicUrls: [],
|
||||
specsList: [],
|
||||
skuList: [],
|
||||
description: null
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
202
src/views/MiniMall/Product/index.vue
Normal file
202
src/views/MiniMall/Product/index.vue
Normal file
@@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
class="-mb-15px"
|
||||
label-width="68px"
|
||||
>
|
||||
<!-- TODO @puhui999:品牌应该是数据下拉哈 -->
|
||||
<el-form-item label="品牌名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
placeholder="请输入品牌名称"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
end-placeholder="结束日期"
|
||||
start-placeholder="开始日期"
|
||||
type="daterange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon class="mr-5px" icon="ep:search" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
重置
|
||||
</el-button>
|
||||
<el-button plain type="primary" @click="openForm">
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
新增
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" class="mt-20px" :data="list" border>
|
||||
<el-table-column type="expand" width="30">
|
||||
<template #default="scope">
|
||||
<div class="pl-100px pr-100px">
|
||||
<el-table :data="scope.row.specsList">
|
||||
<el-table-column label="规格名称" prop="" />
|
||||
<el-table-column label="颜色" prop="color" />
|
||||
<el-table-column label="售价" prop="price" />
|
||||
<el-table-column label="成本价" prop="" />
|
||||
<el-table-column label="简介" prop="intro" />
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column key="id" label="产品编码" prop="id" />
|
||||
<el-table-column show-overflow-tooltip label="产品名称" min-width="200" prop="name" />
|
||||
<el-table-column label="分类" min-width="90" prop="salesCount" />
|
||||
<el-table-column label="品牌" min-width="90" prop="stock" />
|
||||
<el-table-column label="商品图" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-image :src="row.picUrl" @click="imagePreview(row.picUrl)" class="w-30px h-30px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="简介" min-width="70" prop="sort" />
|
||||
<el-table-column :formatter="dateFormatter" label="创建时间" prop="createTime" width="180" />
|
||||
<el-table-column fixed="right" label="操作" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<!-- TODO @puhui999:【详情】,可以后面点做哈 -->
|
||||
<el-button link type="primary" @click="openForm(row.id)"> 修改 </el-button>
|
||||
<el-button link type="danger" @click="handleDelete(row.id)"> 删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
v-model:limit="queryParams.pageSize"
|
||||
v-model:page="queryParams.pageNo"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup name="Product">
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
|
||||
const { currentRoute, push } = useRouter()
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
}) // 查询参数
|
||||
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete() {
|
||||
console.log('123')
|
||||
// try {
|
||||
// // 删除的二次确认
|
||||
// await message.delConfirm()
|
||||
// // 发起删除
|
||||
// // await ProductSpuApi.deleteSpu(id)
|
||||
// message.success(t('common.delSuccess'))
|
||||
// // 刷新列表
|
||||
// await getList()
|
||||
// } catch { }
|
||||
}
|
||||
|
||||
function getList() {
|
||||
list.value = [
|
||||
{
|
||||
id: '1234',
|
||||
name: '爱玩熊攀岩墙',
|
||||
specsList: [
|
||||
{
|
||||
color: '黑色',
|
||||
price: 1234
|
||||
},
|
||||
{
|
||||
color: '灰色',
|
||||
price: 4231
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: '12345',
|
||||
name: '熊攀尼攀岩墙',
|
||||
specsList: [
|
||||
{
|
||||
color: '黑色',
|
||||
price: 12345
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
/** 商品图预览 */
|
||||
function imagePreview(imgUrl) {
|
||||
createImageViewer({
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或修改
|
||||
*
|
||||
* @param id 商品 SPU 编号
|
||||
*/
|
||||
function openForm(id) {
|
||||
// 修改
|
||||
if (typeof id == 'number') {
|
||||
push({
|
||||
path: '/miniMall/productEdit',
|
||||
query: { id }
|
||||
})
|
||||
return
|
||||
}
|
||||
// 新增
|
||||
push('/miniMall/productAdd')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => currentRoute.value,
|
||||
() => {
|
||||
getList()
|
||||
}
|
||||
)
|
||||
|
||||
handleQuery()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo-table-expand {
|
||||
padding-left: 42px;
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
width: 82px;
|
||||
font-weight: bold;
|
||||
color: #99a9bf;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
119
src/views/MiniMall/Purchase/Comp/DialogAdd.vue
Normal file
119
src/views/MiniMall/Purchase/Comp/DialogAdd.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<el-dialog title="发起采购" v-model="dialogVisible" width="800px">
|
||||
<el-form :model="form" ref="addForm" :rules="rules" label-width="100px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="产品" prop="product">
|
||||
<el-select v-model="form.product" placeholder="请选择" filterable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in productOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="规格" prop="specs">
|
||||
<el-select v-model="form.specs" placeholder="请选择" filterable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in specsOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="供应商" prop="supplier">
|
||||
<el-input v-model="form.supplier" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="采购数量" prop="purchaseCount">
|
||||
<el-input-number
|
||||
:min="1"
|
||||
v-model="form.purchaseCount"
|
||||
placeholder="请输入"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="采购单价" prop="price">
|
||||
<el-input-number
|
||||
:min="0"
|
||||
v-model="form.price"
|
||||
placeholder="请输入"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" :offset="0">
|
||||
<el-form-item label="存放仓库" prop="warehouse">
|
||||
<el-select v-model="form.warehouse" placeholder="请选择" filterable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in warehouseOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<Editor v-model:modelValue="form.remark" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSave">保 存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
|
||||
const form = ref()
|
||||
const rules = ref({})
|
||||
|
||||
const productOptions = ref([])
|
||||
const specsOptions = ref([])
|
||||
const warehouseOptions = ref([
|
||||
{ label: '自营仓', value: 1 },
|
||||
{ label: '供应商仓', value: 2 }
|
||||
])
|
||||
|
||||
const open = (val) => {
|
||||
dialogVisible.value = true
|
||||
form.value = val || {
|
||||
product: '',
|
||||
specs: '',
|
||||
supplier: '',
|
||||
purchaseCount: 1,
|
||||
warehouse: 1,
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
function handleSave() {
|
||||
console.log('保存')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
119
src/views/MiniMall/Purchase/Comp/DialogAudit.vue
Normal file
119
src/views/MiniMall/Purchase/Comp/DialogAudit.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<el-dialog title="采购审核" v-model="dialogVisible" width="800px">
|
||||
<Descriptions :data="form" :schema="schema" :columns="3" />
|
||||
<el-form v-if="canEdit" :model="form" ref="auditForm" :rules="rules" label-width="80px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="审核" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :label="2">通过</el-radio>
|
||||
<el-radio :label="3">驳回</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="备注" prop="auditRemark">
|
||||
<Editor v-model:modelValue="form.auditRemark" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSave">保 存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
|
||||
const form = ref({})
|
||||
const rules = ref({})
|
||||
const canEdit = ref(true)
|
||||
|
||||
const schema = ref([
|
||||
{
|
||||
field: 'name',
|
||||
label: '产品名称'
|
||||
},
|
||||
{
|
||||
field: 'specsName',
|
||||
label: '规格名称'
|
||||
},
|
||||
{
|
||||
field: 'supplier',
|
||||
label: '供应商'
|
||||
},
|
||||
{
|
||||
field: 'purchaseCount',
|
||||
label: '采购数量'
|
||||
},
|
||||
{
|
||||
field: 'unitPrice',
|
||||
label: '采购单价'
|
||||
},
|
||||
{
|
||||
field: 'totalPrice',
|
||||
label: '总金额'
|
||||
},
|
||||
{
|
||||
field: 'warehouse',
|
||||
label: '仓库'
|
||||
},
|
||||
{
|
||||
field: 'warehouse',
|
||||
label: '申请人'
|
||||
},
|
||||
{
|
||||
field: '',
|
||||
label: '申请时间'
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
label: '备注',
|
||||
isEditor: true,
|
||||
span: 3
|
||||
}
|
||||
])
|
||||
|
||||
const open = (val, flag) => {
|
||||
dialogVisible.value = true
|
||||
form.value = { ...val, status: 2, remark: '<p style="color: red;">哈哈哈</p>' }
|
||||
canEdit.value = flag
|
||||
if (!canEdit.value) {
|
||||
const arr = [
|
||||
{
|
||||
field: 'status',
|
||||
label: '采购状态'
|
||||
},
|
||||
{
|
||||
field: 'auditUser',
|
||||
label: '审核人'
|
||||
},
|
||||
{
|
||||
field: 'auditTime',
|
||||
label: '审核时间'
|
||||
},
|
||||
{
|
||||
field: 'auditRemark',
|
||||
label: '审核备注',
|
||||
isEditor: true,
|
||||
span: 3
|
||||
}
|
||||
]
|
||||
schema.value = [...schema.value, ...arr]
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
function handleSave() {
|
||||
console.log('保存')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
133
src/views/MiniMall/Purchase/index.data.js
Normal file
133
src/views/MiniMall/Purchase/index.data.js
Normal file
@@ -0,0 +1,133 @@
|
||||
// import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '审核中', value: 1 },
|
||||
{ label: '已通过', value: 2 },
|
||||
{ label: '已驳回', value: 3 }
|
||||
]
|
||||
|
||||
// CrudSchema:https://doc.iocoder.cn/vue3/crud-schema/
|
||||
const crudSchemas = reactive([
|
||||
{
|
||||
label: '产品名称',
|
||||
field: 'name',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '规格名称',
|
||||
field: 'specsName',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '供应商',
|
||||
field: 'supplier',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '采购数量',
|
||||
field: 'purchaseCount',
|
||||
isSearch: false,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '采购单价',
|
||||
field: 'unitPrice',
|
||||
isSearch: false,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '总金额',
|
||||
field: 'totalPrice',
|
||||
isSearch: false,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '仓库',
|
||||
field: 'warehouse',
|
||||
isSearch: false,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '申请人',
|
||||
field: 'applyUserName',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '申请时间',
|
||||
field: 'applyTime',
|
||||
isSearch: true,
|
||||
isTable: true,
|
||||
formatter: dateFormatter,
|
||||
detail: {
|
||||
dateFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
search: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
type: 'daterange',
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
startPlaceholder: '申请时间',
|
||||
endPlaceholder: '申请时间'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '审核人',
|
||||
field: 'auditUserName',
|
||||
isSearch: true,
|
||||
isTable: true
|
||||
},
|
||||
{
|
||||
label: '审核时间',
|
||||
field: 'auditTime',
|
||||
isSearch: true,
|
||||
isTable: true,
|
||||
formatter: dateFormatter,
|
||||
detail: {
|
||||
dateFormat: 'YYYY-MM-DD'
|
||||
},
|
||||
search: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
type: 'daterange',
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
startPlaceholder: '审核时间',
|
||||
endPlaceholder: '审核时间'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '采购状态',
|
||||
field: 'status',
|
||||
isSearch: true,
|
||||
isTable: true,
|
||||
search: {
|
||||
component: 'Select',
|
||||
api: () => statusOptions,
|
||||
componentProps: {
|
||||
optionsAlias: {
|
||||
labelField: 'label',
|
||||
valueField: 'value'
|
||||
}
|
||||
}
|
||||
},
|
||||
table: {
|
||||
field: 'statusName',
|
||||
fixed: 'right'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
field: 'remark',
|
||||
isSearch: false,
|
||||
isTable: true
|
||||
}
|
||||
])
|
||||
export const { allSchemas } = useCrudSchemas(crudSchemas)
|
||||
94
src/views/MiniMall/Purchase/index.vue
Normal file
94
src/views/MiniMall/Purchase/index.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 搜索工作栏 -->
|
||||
<Search
|
||||
:schema="allSchemas.searchSchema"
|
||||
labelWidth="0"
|
||||
expand
|
||||
expand-field="supplier"
|
||||
@search="setSearchParams"
|
||||
@reset="setSearchParams"
|
||||
>
|
||||
<template #actionMore>
|
||||
<el-button type="primary" @click="handleAdd">发起采购</el-button>
|
||||
</template>
|
||||
</Search>
|
||||
<!-- 列表 -->
|
||||
<SSTable
|
||||
class="mt-20px"
|
||||
v-model:tableObject="tableObject"
|
||||
:tableColumns="allSchemas.tableColumns"
|
||||
@get-list="getTableList"
|
||||
>
|
||||
<el-table-column
|
||||
v-for="item in allSchemas.tableColumns"
|
||||
:key="item.table?.field || item.field"
|
||||
:prop="item.table?.field || item.field"
|
||||
:label="item.label"
|
||||
:fixed="item.fixed"
|
||||
min-width="150px"
|
||||
showOverflowTooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="150px" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" v-if="row.status == 1" link @click="handleAudit(row)"
|
||||
>采购审核</el-button
|
||||
>
|
||||
<el-button v-else type="primary" link @click="purchaseAgain(row)">再次采购</el-button>
|
||||
<el-button type="primary" link @click="handleDetail(row)">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</SSTable>
|
||||
<DialogAdd ref="creatPurchase" />
|
||||
<DialogAudit ref="auditPurchase" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { allSchemas } from './index.data.js'
|
||||
import DialogAdd from './Comp/DialogAdd.vue'
|
||||
import DialogAudit from './Comp/DialogAudit.vue'
|
||||
|
||||
const creatPurchase = ref()
|
||||
const auditPurchase = ref()
|
||||
|
||||
const tableObject = ref({
|
||||
tableList: [],
|
||||
loading: false,
|
||||
total: 1,
|
||||
pageSize: 20,
|
||||
currentPage: 1
|
||||
})
|
||||
const setSearchParams = function () {
|
||||
tableObject.value.tableList = [
|
||||
{ name: '测试', status: 1, statusName: '审核中', supplier: '林氏木业', purchaseCount: 10 },
|
||||
{ name: '测试2', status: 2, statusName: '已通过', supplier: '张氏木业', purchaseCount: 1 },
|
||||
{ name: '测试3', status: 3, statusName: '已驳回', supplier: '周氏木业', purchaseCount: 5 }
|
||||
]
|
||||
}
|
||||
|
||||
function getTableList() {
|
||||
tableObject.value.tableList = [
|
||||
{ name: '测试', status: 1, statusName: '审核中', supplier: '林氏木业', purchaseCount: 10 },
|
||||
{ name: '测试2', status: 2, statusName: '已通过', supplier: '张氏木业', purchaseCount: 1 },
|
||||
{ name: '测试3', status: 3, statusName: '已驳回', supplier: '周氏木业', purchaseCount: 5 }
|
||||
]
|
||||
}
|
||||
|
||||
function purchaseAgain(row) {
|
||||
creatPurchase.value.open({ ...row })
|
||||
}
|
||||
|
||||
function handleAudit(row) {
|
||||
auditPurchase.value.open({ ...row }, true)
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
creatPurchase.value.open(null)
|
||||
}
|
||||
function handleDetail(row) {
|
||||
auditPurchase.value.open({ ...row }, false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
Reference in New Issue
Block a user