打包文件

This commit is contained in:
dqz 2025-03-08 08:18:35 +08:00
parent 7e4c1f7daa
commit 1ab653eebe
16 changed files with 669 additions and 63 deletions

View File

@ -2,13 +2,13 @@
# https://cn.vitejs.dev/guide/env-and-mode.html#modes # https://cn.vitejs.dev/guide/env-and-mode.html#modes
# NODE_ENV = development # NODE_ENV = development
VITE_PUBLIC_PATH = ./ VITE_PUBLIC_PATH = /shop-admin/
# 预发布环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数" # 预发布环境路由历史模式Hash模式传"hash"、HTML5模式传"h5"、Hash模式带base参数传"hash,base参数"、HTML5模式带base参数传"h5,base参数"
VITE_ROUTER_HISTORY = "hash" VITE_ROUTER_HISTORY = "hash"
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false # 是否在打包时使用cdn替换本地库 替换 true 不替换 false
VITE_CDN = true VITE_CDN = false
# 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件 # 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认 # 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
@ -16,4 +16,4 @@ VITE_CDN = true
VITE_COMPRESSION = "none" VITE_COMPRESSION = "none"
# 后端地址 # 后端地址
VITE_APP_BASE_API = '/stage-api' VITE_APP_BASE_API = '/shop-back-end'

View File

@ -8,4 +8,5 @@ package.json
commitlint.config.js commitlint.config.js
postcss.config.js postcss.config.js
tailwind.config.js tailwind.config.js
stylelint.config.js stylelint.config.js
build

View File

@ -1,6 +0,0 @@
#!/bin/sh
# shellcheck source=./_/husky.sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit "$1"

View File

@ -1,9 +0,0 @@
#!/bin/sh
command_exists () {
command -v "$1" >/dev/null 2>&1
}
# Workaround for Windows 10, Git Bash and Pnpm
if command_exists winpty && test -t 1; then
exec < /dev/tty
fi

View File

@ -1,8 +0,0 @@
module.exports = {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"{!(package)*.json}": ["prettier --write--parser json"],
"package.json": ["prettier --write"],
"*.vue": ["eslint --fix", "prettier --write", "stylelint --fix"],
"*.{vue,css,scss,postcss,less}": ["stylelint --fix", "prettier --write"],
"*.md": ["prettier --write"]
};

View File

@ -1,10 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/common.sh"
[ -n "$CI" ] && exit 0
# Format and submit code according to lintstagedrc.js configuration
npm run lint:lint-staged
npm run lint:pretty

View File

@ -33,5 +33,10 @@
"cSpell.words": [ "cSpell.words": [
"iconify", "iconify",
"Qrcode" "Qrcode"
] ],
"marscode.codeCompletionPro": {
"enableCodeCompletionPro": true
},
"marscode.enableInlineCommand": true,
"marscode.chatLanguage": "cn"
} }

View File

@ -17,15 +17,6 @@ export function viteBuildInfo(): Plugin {
outDir = resolvedConfig.build?.outDir ?? "dist"; outDir = resolvedConfig.build?.outDir ?? "dist";
}, },
buildStart() { buildStart() {
console.log(
bold(
green(
`👏欢迎使用${blue(
"[Agileboot全栈项目]"
)}star哦💖 https://github.com/valarchie/agileboot-back-end`
)
)
);
if (config.command === "build") { if (config.command === "build") {
startTime = dayjs(new Date()); startTime = dayjs(new Date());
} }

View File

@ -15,7 +15,6 @@ export interface CategoryDTO {
createTime?: Date; createTime?: Date;
updaterId?: number; updaterId?: number;
updateTime?: Date; updateTime?: Date;
deleted?: number;
} }
/** 分类请求参数 */ /** 分类请求参数 */
@ -54,7 +53,7 @@ export const updateCategoryApi = (categoryId: number, data: CategoryRequest) =>
}; };
/** 删除分类 */ /** 删除分类 */
export const deleteCategoryApi = (categoryId: number) => { export const deleteCategoryApi = (categoryId: number | string) => {
return http.request<ResponseData<void>>("delete", `/shop/category/${categoryId}`); return http.request<ResponseData<void>>("delete", `/shop/category/${categoryId}`);
}; };

View File

@ -10,13 +10,13 @@ export interface GoodsQuery extends BasePageQuery {
/** 商品DTO */ /** 商品DTO */
export interface GoodsDTO { export interface GoodsDTO {
goodsId?: number; goodsId?: number;
goodsName?: string; goodsName: string;
categoryId?: number; categoryId: number;
price?: number; price: number;
stock?: number; stock: number;
status?: number; status: number;
coverImg?: string; coverImg: string;
goodsDetail?: string; goodsDetail: string;
creatorId?: number; creatorId?: number;
createTime?: Date; createTime?: Date;
updaterId?: number; updaterId?: number;

View File

@ -20,7 +20,7 @@
"<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>" "<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>"
); );
} catch (t) { } catch (t) {
console && console.log(t); // console && console.log(t);
} }
} }
(n = function () { (n = function () {
@ -28,7 +28,7 @@
c = document.createElement("div"); c = document.createElement("div");
(c.innerHTML = e._iconfont_svg_string_2208059), (c.innerHTML = e._iconfont_svg_string_2208059),
(c = c.getElementsByTagName("svg")[0]) && (c = c.getElementsByTagName("svg")[0]) &&
(c.setAttribute("aria-hidden", "true"), (c.setAttribute("aria-hidden", "true"),
(c.style.position = "absolute"), (c.style.position = "absolute"),
(c.style.width = 0), (c.style.width = 0),
(c.style.height = 0), (c.style.height = 0),
@ -42,11 +42,11 @@
? ~["complete", "loaded", "interactive"].indexOf(document.readyState) ? ~["complete", "loaded", "interactive"].indexOf(document.readyState)
? setTimeout(n, 0) ? setTimeout(n, 0)
: ((l = function () { : ((l = function () {
document.removeEventListener("DOMContentLoaded", l, !1), n(); document.removeEventListener("DOMContentLoaded", l, !1), n();
}), }),
document.addEventListener("DOMContentLoaded", l, !1)) document.addEventListener("DOMContentLoaded", l, !1))
: document.attachEvent && : document.attachEvent &&
((i = n), ((i = n),
(o = e.document), (o = e.document),
(a = !1), (a = !1),
v(), v(),

View File

@ -0,0 +1,115 @@
<script setup lang="ts">
import { reactive, ref, watch } from "vue";
import { FormInstance, FormRules } from "element-plus";
import { updateCategoryApi, addCategoryApi } from "@/api/shop/category";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Confirm from "@iconify-icons/ep/check";
import { ElMessage } from "element-plus";
const props = defineProps({
visible: {
type: Boolean,
default: false
},
row: {
type: Object,
default: null
}
});
const emit = defineEmits(["update:visible", "refresh"]);
const isEdit = ref(false);
const formRef = ref<FormInstance>();
const formData = reactive({
categoryId: 0,
categoryName: "",
sort: 0,
description: ""
});
const rules = reactive<FormRules>({
categoryName: [{
required: true,
message: "分类名称必填",
trigger: "blur"
}],
sort: [{
required: true,
message: "排序值必填",
trigger: "blur",
type: "number"
}]
});
//
const initForm = () => {
if (props.row?.categoryId) {
isEdit.value = true;
Object.assign(formData, props.row);
} else {
isEdit.value = false;
formData.categoryId = 0;
formData.categoryName = "";
formData.sort = 0;
formData.description = "";
}
};
//
const handleConfirm = async () => {
try {
await formRef.value?.validate();
if (isEdit.value) {
await updateCategoryApi(formData.categoryId, formData);
} else {
await addCategoryApi(formData);
}
ElMessage.success(`${isEdit.value ? "修改" : "新增"}成功`);
emit("refresh");
closeDialog();
} catch (error) {
console.error("表单提交失败", error);
}
};
const closeDialog = () => {
formRef.value?.resetFields();
emit("update:visible", false);
};
// visible
watch(
() => props.visible,
val => {
if (val) initForm();
}
);
</script>
<template>
<el-dialog :title="isEdit ? '编辑分类' : '新增分类'" :model-value="visible" width="500px" @close="closeDialog">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px" label-position="right">
<el-form-item label="分类名称" prop="categoryName">
<el-input v-model="formData.categoryName" placeholder="请输入分类名称" clearable />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" class="!w-full" />
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入分类描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
确认
</el-button>
</template>
</el-dialog>
</template>

View File

@ -0,0 +1,107 @@
<script setup lang="ts">
import { reactive, ref, watch } from "vue";
import { FormInstance, FormRules } from "element-plus";
import { addCategoryApi, updateCategoryApi } from "@/api/shop/category";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Confirm from "@iconify-icons/ep/check";
import { ElMessage } from "element-plus";
const props = defineProps({
visible: {
type: Boolean,
default: false
},
row: {
type: Object,
default: null
}
});
const emit = defineEmits(["update:visible", "refresh"]);
const isEdit = ref(false);
const formRef = ref<FormInstance>();
const formData = reactive({
categoryId: 0,
categoryName: "",
sort: 0,
description: ""
});
const rules = reactive<FormRules>({
categoryName: [{ required: true, message: "分类名称必填", trigger: "blur" }],
sort: [{
required: true,
message: "排序值必填",
trigger: "blur",
type: "number"
}]
});
//
const initFormData = () => {
if (props.row) {
Object.assign(formData, props.row);
isEdit.value = true;
} else {
formData.categoryId = 0;
formData.categoryName = "";
formData.sort = 0;
formData.description = "";
isEdit.value = false;
}
};
//
const handleConfirm = async () => {
try {
await formRef.value?.validate();
if (isEdit.value) {
await updateCategoryApi(formData.categoryId, formData);
} else {
await addCategoryApi(formData);
}
ElMessage.success(`${isEdit.value ? "修改" : "新增"}成功`);
emit("refresh");
emit("update:visible", false);
} catch (error) {
console.error("表单提交失败", error);
}
};
// visible
watch(
() => props.visible,
val => {
if (val) {
initFormData();
}
}
);
</script>
<template>
<el-dialog :title="isEdit ? '编辑分类' : '新增分类'" :model-value="visible" width="30%"
@close="emit('update:visible', false)">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="分类名称" prop="categoryName">
<el-input v-model="formData.categoryName" placeholder="请输入分类名称" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" class="!w-full" />
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入分类描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="emit('update:visible', false)">取消</el-button>
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
确定
</el-button>
</template>
</el-dialog>
</template>

View File

@ -0,0 +1,216 @@
<script setup lang="ts">
import { ref } from "vue";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import {
getCategoryListApi,
deleteCategoryApi,
CategoryDTO
} from "@/api/shop/category";
import EditPen from "@iconify-icons/ep/edit-pen";
import Delete from "@iconify-icons/ep/delete";
import AddFill from "@iconify-icons/ri/add-circle-line";
import Search from "@iconify-icons/ep/search";
import Refresh from "@iconify-icons/ep/refresh";
import CategoryFormModal from "./category-form-modal.vue";
import CategoryEditModal from "./category-edit-modal.vue";
import { ElMessage, ElMessageBox } from "element-plus";
defineOptions({
name: "ShopCategory"
});
const formRef = ref();
const tableRef = ref();
const modalVisible = ref(false);
const editVisible = ref(false);
const currentRow = ref<CategoryDTO>();
//
const searchFormParams = ref({
categoryName: "",
sort: null
});
//
const pagination = ref({
pageSize: 10,
currentPage: 1,
total: 0
});
//
const loading = ref(false);
const dataList = ref([]);
const multipleSelection = ref<number[]>([]);
// API
const getList = async () => {
try {
loading.value = true;
const { data } = await getCategoryListApi({
...searchFormParams.value,
pageSize: pagination.value.pageSize,
pageNum: pagination.value.currentPage
});
dataList.value = data.rows;
pagination.value.total = data.total;
} finally {
loading.value = false;
}
};
//
const onSearch = () => {
pagination.value.currentPage = 1;
getList();
};
//
const resetForm = () => {
formRef.value.resetFields();
getList();
};
//
const onSizeChange = (val: number) => {
pagination.value.pageSize = val;
getList();
};
const onCurrentChange = (val: number) => {
pagination.value.currentPage = val;
getList();
};
//
const handleDelete = async (row: any) => {
try {
await ElMessageBox.confirm(
`确认删除分类【${row.categoryName}】?`,
"提示",
{
type: "warning"
}
);
await deleteCategoryApi(row.categoryId);
ElMessage.success("删除成功");
getList();
} catch (error) {
console.error("删除失败", error);
}
};
//
const handleBulkDelete = async () => {
if (multipleSelection.value.length === 0) return;
try {
await ElMessageBox.confirm(
`确认删除选中的${multipleSelection.value.length}项?`,
"提示",
{ type: "warning" }
);
await Promise.all(
multipleSelection.value.map(id => deleteCategoryApi(id))
);
ElMessage.success("批量删除成功");
getList();
} catch (error) {
console.error("批量删除失败", error);
}
};
const handleEdit = (row: CategoryDTO) => {
currentRow.value = row;
editVisible.value = true;
};
//
const columns = [
{
label: "分类名称",
prop: "categoryName"
},
{
label: "排序",
prop: "sort",
width: 120
},
{
label: "描述",
prop: "description",
showOverflowTooltip: true
},
{
label: "创建时间",
prop: "createTime",
width: 180
}
];
//
getList();
</script>
<template>
<div class="main">
<el-form ref="formRef" :inline="true" :model="searchFormParams"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
<el-form-item label="分类名称:" prop="categoryName">
<el-input v-model="searchFormParams.categoryName" placeholder="请输入分类名称" clearable class="!w-[200px]" />
</el-form-item>
<el-form-item label="排序:" prop="sort">
<el-input-number v-model="searchFormParams.sort" :min="0" class="!w-[120px]" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="useRenderIcon(Search)" @click="onSearch">
搜索
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm">
重置
</el-button>
</el-form-item>
</el-form>
<PureTableBar title="分类列表" @refresh="getList">
<template #buttons>
<el-button type="primary" :icon="useRenderIcon(AddFill)" @click="modalVisible = true">
新增分类
</el-button>
<el-button type="danger" :icon="useRenderIcon(Delete)" :disabled="multipleSelection.length === 0"
@click="handleBulkDelete">
批量删除
</el-button>
</template>
<el-table ref="tableRef" v-loading="loading" :data="dataList" row-key="categoryId"
@selection-change="val => multipleSelection = val.map(item => item.categoryId)">
<el-table-column type="selection" width="55" />
<el-table-column v-for="col in columns" :key="col.prop" :prop="col.prop" :label="col.label" :width="col.width"
:show-overflow-tooltip="col.showOverflowTooltip" />
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEdit(row)">
编辑
</el-button>
<el-popconfirm :title="`确认删除【${row.categoryName}】?`" @confirm="handleDelete(row)">
<template #reference>
<el-button type="danger" link :icon="useRenderIcon(Delete)">
删除
</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"
@size-change="onSizeChange" @current-change="onCurrentChange" />
</PureTableBar>
<category-form-modal v-model:visible="modalVisible" @refresh="getList" />
<category-edit-modal v-model:visible="editVisible" :row="currentRow" @refresh="getList" />
</div>
</template>

View File

@ -0,0 +1,195 @@
<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import { ElMessage, FormRules } from "element-plus";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { GoodsDTO, updateGoodsApi, addGoodsApi } from "@/api/shop/goods";
import { CategoryDTO, getCategoryAllApi } from "@/api/shop/category";
import Confirm from "@iconify-icons/ep/check";
import Upload from "@iconify-icons/ep/upload";
const { VITE_APP_BASE_API } = import.meta.env;
const props = defineProps({
visible: {
type: Boolean,
default: false
},
row: {
type: Object as () => GoodsDTO,
default: null
}
});
const emit = defineEmits(["update:visible", "refresh"]);
const formRef = ref();
const isEdit = ref(false);
const formData = reactive<GoodsDTO>({
goodsId: 0,
goodsName: "",
price: 0,
stock: 0,
status: 1,
categoryId: 0,
goodsDetail: "",
coverImg: ""
});
const rules = reactive<FormRules>({
goodsName: [{ required: true, message: "商品名称必填", trigger: "blur" }],
price: [
{ required: true, message: "价格必填", trigger: "blur" },
{ type: 'number', min: 0, message: '价格不能小于0' }
],
stock: [
{ required: true, message: "库存必填", trigger: "blur" },
{ type: 'number', min: 0, message: '库存不能小于0' }
],
coverImg: [
{ required: true, message: "请上传商品封面图", trigger: "change" }
]
});
const handleConfirm = async () => {
try {
await formRef.value.validate();
if (isEdit.value) {
await updateGoodsApi(formData.goodsId!, formData);
ElMessage.success("商品修改成功");
} else {
await addGoodsApi(formData);
ElMessage.success("商品添加成功");
}
emit("refresh");
closeDialog();
} catch (error) {
console.error("表单操作失败", error);
}
};
const closeDialog = () => {
formRef.value.resetFields();
emit("update:visible", false);
};
const categoryOptions = ref<Array<CategoryDTO>>([]);
//
const initForm = async () => {
try {
//
const { data } = await getCategoryAllApi();
categoryOptions.value = data;
//
if (props.row?.goodsId) {
isEdit.value = true;
Object.assign(formData, props.row);
//
formData.price = Number(formData.price);
formData.stock = Number(formData.stock);
} else {
isEdit.value = false;
if (data.length > 0) {
formData.categoryId = data[0].categoryId;
}
}
} catch (e) {
console.error("数据加载失败", e);
}
};
const handleAvatarSuccess = (response, uploadFile) => {
formData.coverImg = response.data.url;
};
const beforeAvatarUpload = (rawFile) => {
if (!['image/jpeg', 'image/png'].includes(rawFile.type)) {
ElMessage.error('封面图必须是 JPG/PNG 格式!')
return false
}
if (rawFile.size > 50 * 1024 * 1024) {
ElMessage.error('封面图大小不能超过 50MB!')
return false
}
return true
};
watch(
() => props.visible,
val => {
if (val) initForm();
}
);
</script>
<template>
<el-dialog :title="isEdit ? '编辑商品' : '新增商品'" :model-value="visible" width="600px" @close="closeDialog">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px" label-position="right">
<el-form-item label="商品名称" prop="goodsName">
<el-input v-model="formData.goodsName" placeholder="请输入商品名称" clearable />
</el-form-item>
<el-form-item label="封面图" prop="coverImg">
<el-upload class="avatar-uploader" :action="VITE_APP_BASE_API + '/file/upload'" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="formData.coverImg" :src="formData.coverImg" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Icon :icon="Upload" />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input-number v-model="formData.price" :min="0" :precision="2" controls-position="right" />
</el-form-item>
<el-form-item label="库存" prop="stock">
<el-input-number v-model="formData.stock" :min="0" controls-position="right" />
</el-form-item>
<el-form-item label="商品分类" prop="categoryId">
<el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full">
<el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName"
:value="category.categoryId" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">上架</el-radio>
<el-radio :label="2">下架</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="closeDialog">取消</el-button>
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
确认
</el-button>
</template>
</el-dialog>
</template>
<style scoped>
.avatar-uploader {
:deep(.el-upload) {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
&:hover {
border-color: var(--el-color-primary);
}
}
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>

View File

@ -2,13 +2,14 @@
import { ref } from "vue"; import { ref } from "vue";
import { PureTableBar } from "@/components/RePureTableBar"; import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { getGoodsListApi } from "@/api/shop/goods"; import { getGoodsListApi, GoodsDTO } from "@/api/shop/goods";
import EditPen from "@iconify-icons/ep/edit-pen"; import EditPen from "@iconify-icons/ep/edit-pen";
import Delete from "@iconify-icons/ep/delete"; import Delete from "@iconify-icons/ep/delete";
import AddFill from "@iconify-icons/ri/add-circle-line"; import AddFill from "@iconify-icons/ri/add-circle-line";
import Search from "@iconify-icons/ep/search"; import Search from "@iconify-icons/ep/search";
import Refresh from "@iconify-icons/ep/refresh"; import Refresh from "@iconify-icons/ep/refresh";
import GoodsFormModal from "./goods-form-modal.vue"; import GoodsFormModal from "./goods-form-modal.vue";
import GoodsEditModal from "./goods-edit-modal.vue";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { deleteGoodsApi } from "@/api/shop/goods"; import { deleteGoodsApi } from "@/api/shop/goods";
@ -37,6 +38,8 @@ const pagination = ref({
const loading = ref(false); const loading = ref(false);
const dataList = ref([]); const dataList = ref([]);
const multipleSelection = ref<number[]>([]); const multipleSelection = ref<number[]>([]);
const editVisible = ref(false);
const currentRow = ref<GoodsDTO>();
const getList = async () => { const getList = async () => {
try { try {
@ -115,6 +118,12 @@ const handleBulkDelete = async () => {
const handleSelectionChange = (rows: any[]) => { const handleSelectionChange = (rows: any[]) => {
multipleSelection.value = rows.map(row => row.goodsId); multipleSelection.value = rows.map(row => row.goodsId);
}; };
const handleEdit = (row: GoodsDTO) => {
currentRow.value = row;
editVisible.value = true;
};
</script> </script>
<template> <template>
@ -171,7 +180,7 @@ const handleSelectionChange = (rows: any[]) => {
</el-table-column> </el-table-column>
<el-table-column label="操作" width="150" fixed="right"> <el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button type="primary" link :icon="useRenderIcon(EditPen)"> <el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEdit(row)">
编辑 编辑
</el-button> </el-button>
<el-popconfirm :title="`确认删除【${row.goodsName}】?`" @confirm="handleDelete(row)"> <el-popconfirm :title="`确认删除【${row.goodsName}】?`" @confirm="handleDelete(row)">
@ -190,6 +199,7 @@ const handleSelectionChange = (rows: any[]) => {
</PureTableBar> </PureTableBar>
<!-- 新增商品弹窗 --> <!-- 新增商品弹窗 -->
<goods-form-modal v-model:visible="modalVisible" @refresh="getList" /> <goods-form-modal v-model:visible="modalVisible" @refresh="getList" />
<goods-edit-modal v-model:visible="editVisible" :row="currentRow" @refresh="getList" />
</div> </div>
</template> </template>
<style scoped> <style scoped>