“陈博论” 10 місяців тому
батько
коміт
aa2d5b9b22

+ 0 - 0
web/src/views/backend/product/combo/detail.vue → web/src/views/backend/package/package/detail.vue


+ 176 - 0
web/src/views/backend/package/package/index.vue

@@ -0,0 +1,176 @@
+<template>
+    <!-- 外层容器,保持默认的表格布局框架 -->
+    <div class="default-main ba-table-box">
+        <!-- 备注提示,当有 remark 时展示 -->
+        <el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info"
+            show-icon />
+
+        <!-- 顶部筛选与新增区域,左侧输入与下拉,右侧添加按钮 -->
+        <!-- 表格顶部菜单 -->
+        <TableHeader :buttons="['refresh', 'columnDisplay']"
+            :quick-search-placeholder="t('Quick search placeholder', { fields: '产品名称' })">
+            <!-- 套餐名称输入框,支持清空 -->
+            <el-input class="filter-item" v-model="searchForm.name" placeholder="套餐名称" clearable @input="handleFilter"
+                @clear="handleFilter" />
+            <!-- 库存状态选择框,模拟原型的状态下拉 -->
+            <el-select class="filter-item" v-model="searchForm.inventory_status" placeholder="库存状态" clearable
+                @change="handleFilter" @clear="handleFilter">
+                <el-option v-for="item in inventoryOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <!-- 右侧添加按钮 -->
+            <el-button type="primary" @click="onAdd">添加</el-button>
+        </TableHeader>
+        <!-- 表格主体,使用通用 Table 组件并自定义操作列 -->
+        <Table>
+            <!-- 自定义操作列插槽,呈现编辑/删除/详情 -->
+            <template #operate>
+                <el-table-column prop="operate" align="center" label="操作" min-width="180">
+                    <template #default="scope">
+                        <el-button type="primary" size="small" @click="onEdit(scope.row)">编辑</el-button>
+                        <el-button type="danger" size="small" @click="del(scope.row)">删除</el-button>
+                        <el-button style="color: #fff;" color="#9ca0fa" size="small"
+                            @click="viewDetail(scope.row)">套餐详情</el-button>
+                    </template>
+                </el-table-column>
+            </template>
+        </Table>
+
+        <!-- 添加编辑弹框 -->
+        <PopupForm ref="popupFormRef"/>
+
+        <!-- 套餐详情 / 库存调整弹框 -->
+        <Detail ref="detailRef" @confirm="handleDetailConfirm" />
+
+    </div>
+</template>
+
+<script setup lang="ts">
+// 引入响应式工具与生命周期钩子
+import { provide, reactive, ref } from 'vue'
+// 引入表格封装类
+import baTableClass from '/@/utils/baTable'
+// 引入通用表格组件
+import Table from '/@/components/table/index.vue'
+import TableHeader from '/@/components/table/header/index.vue'
+import PopupForm from './popupForm.vue'
+import Detail from './detail.vue'
+// 引入接口封装
+import { baTableApi } from '/@/api/common'
+// 引入国际化
+import { useI18n } from 'vue-i18n'
+// 引入消息提示
+import { ElMessage } from 'element-plus'
+
+// 组件名称定义
+defineOptions({
+    name: 'package/package',
+})
+
+// 国际化方法
+const { t } = useI18n()
+
+const popupFormRef = ref<InstanceType<typeof PopupForm>>()
+const detailRef = ref<InstanceType<typeof Detail>>()
+
+// 筛选表单数据,包含套餐名称与库存状态
+const searchForm = reactive({
+    name: '', // 套餐名称关键词
+    inventory_status: '', // 库存状态筛选值
+})
+
+// 库存状态选项,映射下拉显示
+const inventoryOptions = [
+    { label: '充足', value: '1' },
+    { label: '即将售罄', value: '2' },
+    { label: '售罄', value: '3' },
+]
+
+// 初始化表格实例,配置列信息
+const baTable = new baTableClass(
+    new baTableApi('/admin/package.package/'),
+    {
+        column: [
+            { label: '编号', prop: 'id', align: 'center', width: 70 },
+            { label: '套餐名称', prop: 'name', align: 'center', minWidth: 140 },
+            {
+                label: '库存状态',
+                prop: 'inventory_status',
+                align: 'center',
+                render: 'tag',
+                custom: { '1': 'primary', '2': 'warning', '3': 'danger' },
+                replaceValue: { '1': '充足', '2': '即将售罄', '3': '售罄' },
+                effect: 'plain',
+                minWidth: 120,
+            },
+            {
+                label: '剩余库存',
+                prop: 'remaining_stock',
+                align: 'center',
+                minWidth: 140,
+            },
+            { label: '已卖数量', prop: 'sold_quantity', align: 'center', minWidth: 100 },
+            { label: '创建时间', prop: 'create_time', align: 'center', minWidth: 160 },
+            { label: '操作', align: 'center', render: 'slot', slotName: 'operate', operator: false, minWidth: 180 },
+        ],
+        dblClickNotEditColumn: [undefined],
+    },
+    {
+        defaultItems: {
+            name: '',
+            inventory_status: '1',
+        },
+    },
+    {
+        onTableDblclick: () => {
+            return false
+        },
+    },
+)
+
+// 注入表格实例供子组件使用
+baTable.mount()
+baTable.getData()
+provide('baTable', baTable)
+
+// 删除动作,展示提示
+const del = (row: TableRow) => {
+    ElMessage.success(`已删除套餐:${row.name}`)
+}
+
+// 编辑动作:打开弹框并带入当前行
+const onEdit = (row: TableRow) => {
+    popupFormRef.value?.editDialog(row)
+}
+
+// 新增动作,展示提示
+const onAdd = () => {
+    popupFormRef.value?.openDialog()
+}
+
+
+// 套餐详情动作,弹出详情弹框,可从按钮或库存单元格进入
+const viewDetail = (row: Record<string, any>, fromStockClick = false) => {
+    if (!row) return
+    detailRef.value?.open(row as any)
+    if (!fromStockClick) {
+        ElMessage.success(`查看套餐详情:${row.name}`)
+    }
+}
+
+// 详情弹框确认修改库存
+const handleDetailConfirm = () => {
+
+}
+
+// 输入或选择变化时触发过滤
+const handleFilter = () => {
+    baTable.getData()
+}
+</script>
+
+<style scoped lang="scss">
+.filter-item {
+    width: 180px;
+    margin: 0 6px;
+}
+</style>

+ 0 - 0
web/src/views/backend/product/combo/popupForm.vue → web/src/views/backend/package/package/popupForm.vue


+ 2 - 2
web/src/views/backend/product/product/index.vue → web/src/views/backend/package/product/index.vue

@@ -48,13 +48,13 @@ import { useI18n } from 'vue-i18n'
 type TableRow = Record<string, any>
 
 defineOptions({
-    name: 'product/product',
+    name: 'package/product',
 })
 
 const { t } = useI18n()
 
 const baTable = new baTableClass(
-    new baTableApi('/admin/product.product/'),
+    new baTableApi('/admin/package.product/'),
     {
         column: [
             { label: '编号', prop: 'id', align: 'center', width: 70 },

+ 0 - 0
web/src/views/backend/product/product/popupForm.vue → web/src/views/backend/package/product/popupForm.vue


+ 0 - 362
web/src/views/backend/product/combo/index.vue

@@ -1,362 +0,0 @@
-<template>
-    <!-- 外层容器,保持默认的表格布局框架 -->
-    <div class="default-main ba-table-box">
-        <!-- 备注提示,当有 remark 时展示 -->
-        <el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
-
-        <!-- 顶部筛选与新增区域,左侧输入与下拉,右侧添加按钮 -->
-         <!-- 表格顶部菜单 -->
-        <TableHeader :buttons="['refresh', 'columnDisplay']"
-            :quick-search-placeholder="t('Quick search placeholder', { fields: '产品名称' })">
-            <!-- 套餐名称输入框,支持清空 -->
-            <el-input
-                class="filter-item"
-                v-model="searchForm.name"
-                placeholder="套餐名称"
-                clearable
-                @input="handleFilter"
-                @clear="handleFilter"
-            />
-            <!-- 库存状态选择框,模拟原型的状态下拉 -->
-            <el-select
-                class="filter-item"
-                v-model="searchForm.inventory_status"
-                placeholder="库存状态"
-                clearable
-                @change="handleFilter"
-                @clear="handleFilter"
-            >
-                <el-option
-                    v-for="item in inventoryOptions"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                />
-            </el-select>
-            <!-- 右侧添加按钮 -->
-            <el-button type="primary" @click="onAdd">添加</el-button>
-        </TableHeader>
-        <!-- 表格主体,使用通用 Table 组件并自定义操作列 -->
-        <Table>
-            <!-- 自定义操作列插槽,呈现编辑/删除/详情 -->
-            <template #operate>
-                <el-table-column prop="operate" align="center" label="操作" min-width="180">
-                    <template #default="scope">
-                        <el-button  type="primary" size="small" @click="onEdit(scope.row)">编辑</el-button>
-                        <el-button  type="danger" size="small" @click="del(scope.row)">删除</el-button>
-                        <el-button style="color: #fff;"  color="#9ca0fa" size="small" @click="viewDetail(scope.row)">套餐详情</el-button>
-                    </template>
-                </el-table-column>
-            </template>
-        </Table>
-
-        <!-- 添加编辑弹框 -->
-        <PopupForm ref="popupFormRef" @success="handleFormSuccess" />
-
-        <!-- 套餐详情 / 库存调整弹框 -->
-        <Detail ref="detailRef" @confirm="handleDetailConfirm" />
-
-    </div>
-</template>
-
-<script setup lang="ts">
-// 引入响应式工具与生命周期钩子
-import { onMounted, provide, reactive, ref } from 'vue'
-// 引入表格封装类
-import baTableClass from '/@/utils/baTable'
-// 引入通用表格组件
-import Table from '/@/components/table/index.vue'
-import TableHeader from '/@/components/table/header/index.vue'
-import PopupForm from './popupForm.vue'
-import Detail from './detail.vue'
-// 引入接口封装
-import { baTableApi } from '/@/api/common'
-// 引入国际化
-import { useI18n } from 'vue-i18n'
-// 引入消息提示
-import { ElMessage } from 'element-plus'
-
-// 组件名称定义
-defineOptions({
-    name: 'application/combo',
-})
-
-// 国际化方法
-const { t } = useI18n()
-
-const popupFormRef = ref<InstanceType<typeof PopupForm>>()
-const detailRef = ref<InstanceType<typeof Detail>>()
-
-// 筛选表单数据,包含套餐名称与库存状态
-const searchForm = reactive({
-    name: '', // 套餐名称关键词
-    inventory_status: '', // 库存状态筛选值
-})
-
-// 库存状态选项,映射下拉显示
-const inventoryOptions = [
-    { label: '充足', value: '1' },
-    { label: '即将售罄', value: '2' },
-    { label: '售罄', value: '3' },
-]
-
-// 静态模拟数据,来源于原型图 + 规格示例数据
-// 规格字段与 popupForm 中的 SpecificationItem 一致,方便后续联动编辑
-const baseData = [
-    {
-        id: 1,
-        name: '聚德神笔',
-        inventory_status: '1',
-        remaining_stock: 120,
-        sold_quantity: 12,
-        create_time: '2025-10-19',
-        specificationsList: [
-            {
-                specName: '个人基础版',
-                price: 99,
-                stock: 80,
-                packageType: '1', // 个人套餐
-                chargeType: '1', // 按次数
-                quantity: 10,
-                remark: '适合个人日常使用',
-            },
-            {
-                specName: '个人进阶版',
-                price: 199,
-                stock: 40,
-                packageType: '1',
-                chargeType: '2', // 按积分
-                quantity: 100,
-                remark: '附赠额外积分',
-            },
-        ],
-    },
-    {
-        id: 2,
-        name: '棱镜',
-        inventory_status: '2',
-        remaining_stock: 12,
-        sold_quantity: 88,
-        create_time: '2025-10-19',
-        specificationsList: [
-            {
-                specName: '团队标准版',
-                price: 599,
-                stock: 8,
-                packageType: '2', // 团队套餐
-                chargeType: '3', // 日卡
-                quantity: undefined,
-                remark: '适合小团队短期使用',
-            },
-            {
-                specName: '团队增强版',
-                price: 1599,
-                stock: 4,
-                packageType: '2',
-                chargeType: '5', // 月卡
-                quantity: undefined,
-                remark: '按月计费,支持多人使用',
-            },
-        ],
-    },
-    {
-        id: 3,
-        name: '套装示例',
-        inventory_status: '3',
-        remaining_stock: 0,
-        sold_quantity: 120,
-        create_time: '2025-10-19',
-        specificationsList: [
-            {
-                specName: '体验版',
-                price: 49,
-                stock: 0,
-                packageType: '1',
-                chargeType: '1',
-                quantity: 3,
-                remark: '促销活动已售罄',
-            },
-        ],
-    },
-]
-
-// 初始化表格实例,配置列信息
-const baTable = new baTableClass(
-    new baTableApi('/admin/application.combo'),
-    {
-        column: [
-            { label: '编号', prop: 'id', align: 'center', width: 70 },
-            { label: '套餐名称', prop: 'name', align: 'center', minWidth: 140 },
-            {
-                label: '库存状态',
-                prop: 'inventory_status',
-                align: 'center',
-                render: 'tag',
-                custom: { '1': 'primary', '2': 'warning', '3': 'danger' },
-                replaceValue: { '1': '充足', '2': '即将售罄', '3': '售罄' },
-                effect: 'plain',
-                minWidth: 120,
-            },
-            {
-                label: '剩余库存',
-                prop: 'remaining_stock',
-                align: 'center',
-                minWidth: 140,
-            },
-            { label: '已卖数量', prop: 'sold_quantity', align: 'center', minWidth: 100 },
-            { label: '创建时间', prop: 'create_time', align: 'center', minWidth: 160 },
-            { label: '操作', align: 'center', render: 'slot', slotName: 'operate', operator: false, minWidth: 180 },
-        ],
-        dblClickNotEditColumn: [undefined],
-    },
-    {
-        defaultItems: {
-            name: '',
-            inventory_status: '1',
-            remaining_stock: 0,
-            sold_quantity: 0,
-        },
-    },
-    {
-		onTableDblclick: () => {
-			return false
-		},
-	},
-)
-
-// 覆写获取数据方法,基于筛选条件过滤静态数据
-baTable.getData = () => {
-    baTable.table.loading = true // 开启加载状态
-    return new Promise<void>((resolve) => {
-        setTimeout(() => {
-            // 根据输入与下拉值过滤数据
-            const filtered = baseData.filter((item) => {
-                const matchName = searchForm.name ? item.name.includes(searchForm.name.trim()) : true
-                const matchStatus = searchForm.inventory_status ? item.inventory_status === searchForm.inventory_status : true
-                return matchName && matchStatus
-            })
-            baTable.table.data = filtered // 写入表格数据
-            baTable.table.total = filtered.length // 写入总数
-            baTable.table.loading = false // 关闭加载状态
-            resolve() // 完成 Promise
-        }, 200)
-    })
-}
-
-// 删除动作,展示提示
-const del = (row:TableRow) => {
-    ElMessage.success(`已删除套餐:${row.name}`)
-}
-
-// 编辑动作:打开弹框并带入当前行
-const onEdit = (row:TableRow ) => {
-    popupFormRef.value?.editDialog(row as any)
-}
-
-// 新增动作,展示提示
-const onAdd = () => {
-    popupFormRef.value?.openDialog()
-}
-
-// 处理弹框提交成功(新增 / 编辑)
-const handleFormSuccess = (payload: {
-    id: number | null
-    type: 'add' | 'edit'
-    name: string
-    specificationsList: any[]
-}) => {
-    const { id, type, name, specificationsList } = payload
-
-    // 根据规格列表计算总库存
-    const totalStock = (specificationsList || []).reduce(
-        (sum, item) => sum + (Number(item.stock) || 0),
-        0
-    )
-
-    // 根据库存计算库存状态
-    let inventoryStatus = '1' // 充足
-    if (totalStock === 0) {
-        inventoryStatus = '3' // 售罄
-    } else if (totalStock < 10) {
-        inventoryStatus = '2' // 即将售罄
-    }
-
-    if (type === 'edit' && id != null) {
-        // 编辑:更新静态数据中的对应项
-        const target = baseData.find((item) => item.id === id)
-        if (target) {
-            target.name = name
-            target.remaining_stock = totalStock
-            target.inventory_status = inventoryStatus
-            // 把规格明细也一起带上,方便下次再编辑
-            ;(target as any).specificationsList = specificationsList
-            ElMessage.success(`已更新套餐:${name}`)
-        }
-    } else {
-        // 新增:简单提示(此处仍以静态数据为主,不追加行)
-        ElMessage.success(`已添加套餐:${name}`)
-    }
-
-    // 重新根据筛选条件刷新一次表格
-    baTable.getData()
-}
-
-// 套餐详情动作,弹出详情弹框,可从按钮或库存单元格进入
-const viewDetail = (row: Record<string, any>, fromStockClick = false) => {
-    if (!row) return
-    detailRef.value?.open(row as any)
-    if (!fromStockClick) {
-        ElMessage.success(`查看套餐详情:${row.name}`)
-    }
-}
-
-// 详情弹框确认修改库存
-const handleDetailConfirm = (payload: {
-    id: number
-    specificationsList: any[]
-    totalStock: number
-}) => {
-    const target = baseData.find((item) => item.id === payload.id)
-    if (!target) return
-
-    // 更新规格明细
-    ;(target as any).specificationsList = payload.specificationsList
-
-    // 更新总库存
-    target.remaining_stock = payload.totalStock
-
-    // 根据总库存刷新库存状态
-    if (payload.totalStock === 0) {
-        target.inventory_status = '3'
-    } else if (payload.totalStock < 10) {
-        target.inventory_status = '2'
-    } else {
-        target.inventory_status = '1'
-    }
-
-    ElMessage.success(`已更新「${target.name}」的库存信息`)
-    baTable.getData()
-}
-
-// 输入或选择变化时触发过滤
-const handleFilter = () => {
-    baTable.getData()
-}
-
-// 注入表格实例供子组件使用
-provide('baTable', baTable)
-
-// 初始化挂载表格并拉取数据
-onMounted(() => {
-    baTable.mount()
-    baTable.getData()
-})
-</script>
-
-<style scoped lang="scss">
-.filter-item {
-    width: 180px;
-    margin: 0 6px;
-}
-</style>
-