init:初始化多余的,添加班型列表

This commit is contained in:
lwh 2023-04-18 21:18:17 +08:00
parent 3212142d8f
commit 4afb54f41a
29 changed files with 174 additions and 5059 deletions

4
.env
View File

@ -1,6 +1,6 @@
# 后台接口地址(仅开发/预览环境生效)
VITE_PROXY_API=http://localhost/AERWEN/php_web/php_web_api/public/admin.php/
VITE_PROXY_API=http://localhost/AERWEN/houde_web/houde_web_api/public/admin.php/
# 后台图片地址(仅开发/预览环境生效)
VITE_PROXY_UPLOADS=http://localhost/AERWEN/php_web/php_web_api/public/uploads/
VITE_PROXY_UPLOADS=http://localhost/AERWEN/houde_web/houde_web_api/public/uploads/
# 后台富文本上传地址(仅开发/预览环境生效)
VITE_PROXY_RICHTEXT=http://localhost:3000/api/

View File

@ -1,12 +1,27 @@
<template>
<el-dialog v-model="dialogVisible" title="添加班" width="900px" @closed="closeDialog" @open="openDialog">
<el-dialog v-model="dialogVisible" title="添加班" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入班级名称'></el-input>
<el-form-item :label-width="labelWidth" label="名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="简介" prop="classes_desc">
<el-input v-model='formData.classes_desc' type="textarea" :rows="5" placeholder='请输入简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="内容" prop="classes_content">
<RichText v-model='formData.classes_content' :min-height='196'></RichText>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="排序" prop="classes_sort">
<el-input-number v-model='formData.classes_sort' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
@ -66,7 +81,19 @@ const rules = reactive({
classes_name: [
{
required: true,
message: '班级名称不能为空'
message: '名称不能为空'
}
],
classes_content: [
{
required: true,
message: '内容不能为空'
}
],
classes_sort: [
{
required: true,
message: '排序不能为空'
}
],

View File

@ -1,17 +1,27 @@
<template>
<el-dialog v-model="props.modelValue" title="产品参数详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-dialog v-model="props.modelValue" title="班型详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品参数名称" prop="product_param_name">
<el-input v-model='formData.product_param_name' type="text" placeholder='请输入产品参数名称'></el-input>
<el-form-item :label-width="labelWidth" label="名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-input v-model='formData.product_type_guid' type="text" placeholder='请输入产品系列'></el-input>
<el-form-item :label-width="labelWidth" label="简介" prop="classes_desc">
<el-input v-model='formData.classes_desc' type="textarea" :rows="5" placeholder='请输入简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="内容" prop="classes_content">
<RichText v-model='formData.classes_content' :min-height='196'></RichText>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="排序" prop="classes_sort">
<el-input-number v-model='formData.classes_sort' controls-position='right'></el-input-number>
</el-form-item>
</el-col>

View File

@ -1,12 +1,27 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑班" width="900px" @closed="closeDialog" @open="openDialog">
<el-dialog v-model="props.modelValue" title="编辑班" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入班级名称'></el-input>
<el-form-item :label-width="labelWidth" label="名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="简介" prop="classes_desc">
<el-input v-model='formData.classes_desc' type="textarea" :rows="5" placeholder='请输入简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="内容" prop="classes_content">
<RichText v-model='formData.classes_content' :min-height='196'></RichText>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="排序" prop="classes_sort">
<el-input-number v-model='formData.classes_sort' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
@ -61,12 +76,13 @@ const uoloadData = ref({
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
};
const closeDialog = () => {
@ -78,7 +94,19 @@ const rules = reactive({
classes_name: [
{
required: true,
message: '班级名称不能为空'
message: '名称不能为空'
}
],
classes_content: [
{
required: true,
message: '内容不能为空'
}
],
classes_sort: [
{
required: true,
message: '排序不能为空'
}
],

View File

@ -1,14 +1,15 @@
<template><!-- 面包屑 -->
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>管理</el-breadcrumb-item>
<el-breadcrumb-item to="/classes/list">列表</el-breadcrumb-item>
<el-breadcrumb-item>管理</el-breadcrumb-item>
<el-breadcrumb-item to="/classes/list">列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="班级名称">
<el-input v-model='params.classes_name' placeholder='请输入班级名称'></el-input>
<el-form-item label="名称">
<el-input v-model='params.classes_name' placeholder='请输入名称'></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
@ -17,12 +18,24 @@
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加班 -->
<!-- 添加班 -->
<el-col :span="1">
<el-button type="primary" @click="addClassesDialogVisible = true"> 添加 </el-button>
</el-col>
<!-- 导出 -->
<el-button icon="ElIconDocument" @click="exportExcel(params)">导出</el-button>
<!-- 导入 -->
<el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
<el-button type="primary">导入</el-button>
</el-upload>
<!-- 下载导入模板 -->
<el-button icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button>
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
@ -42,6 +55,7 @@
<DataTable ref="tableRef" style="width: 100%" :onSelectionChange="data => (selectionData = data)" :column="column"
:params="params" :request="params => getClassesList(params)">
<template #chaoz="scope">
<el-space>
<el-button size="small" @click="handleUpdate(scope.row)">
@ -66,19 +80,19 @@
</template>
</DataTable>
<!-- 添加班 -->
<!-- 添加班 -->
<AddClassesDialog v-model="addClassesDialogVisible" :done="() => tableRef.reload()"></AddClassesDialog>
<!-- 编辑班 -->
<!-- 编辑班 -->
<EditClassesDialog v-model="EditClassesDialogVisible" :data="EditClassesDialogRow" :done="() => tableRef.reload()">
</EditClassesDialog>
<!-- 详情 -->
<!-- 详情 -->
<DetailClassesDialog v-model="DetailClassesDialogVisible" :data="DetailClassesDialogRow"></DetailClassesDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive } from 'vue';
import { useLoginStore } from "~/store";
import { getClassesList, deleteClasses } from '~/service/classes';
import { getClassesList, deleteClasses, exportExcel, downloadTemplate, importExcel } from '~/service/classes';
import AddClassesDialog from './components/AddClassesDialog.vue';
import EditClassesDialog from './components/EditClassesDialog.vue';
import DetailClassesDialog from './components/DetailClassesDialog.vue';
@ -111,7 +125,17 @@ const column = [
},
{
prop: "classes_name",
label: '班级名称',
label: '名称',
width: '150'
},
{
prop: "classes_desc",
label: '简介',
width: '150'
},
{
prop: "classes_sort",
label: '排序',
width: '150'
},
{
@ -135,7 +159,7 @@ const handleCommand = ({ type, row }) => {
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该班吗?`).then(async () => {
ElMessageBox.confirm(`您确定要删除该班吗?`).then(async () => {
const res = await deleteClasses({
classes_guid: data.map(v => v.classes_guid).join()
});
@ -158,6 +182,30 @@ function handleDetail(row) {
}
//
let loadingImoprt = null;
const uploadLoading = () => {
loadingImoprt = ElLoading.service({
lock: true,
text: "正在导入中...",
background: "rgba(255, 255, 255, 0.7)",
});
};
const closeUploadLoading = () => loadingImoprt.close();
const handleExcelSuccess = (value) => {
if (value.code == 0) {
ElMessageBox.alert(value.msg, "导入信息", {
dangerouslyUseHTMLString: true,
confirmButtonText: "确定",
});
} else {
ElMessage.error(value.msg);
}
closeUploadLoading();
tableRef.value.reload();
};
</script>

View File

@ -1,187 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="添加新闻" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻标题" prop="news_title">
<el-input v-model='formData.news_title' type="text" placeholder='请输入新闻标题'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻作者" prop="news_author">
<el-input v-model='formData.news_author' type="text" placeholder='请输入新闻作者'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻简介" prop="news_intro">
<el-input v-model='formData.news_intro' type="textarea" placeholder='请输入新闻简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="新闻类型" prop="news_type" :label-width="labelWidth">
<el-select v-model="formData.news_type" clearable placeholder="请选择">
<el-option v-for="item in news_typee" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='新闻封面图片' prop='news_img'>
<UploadImage ref='uploadRef' v-model='formData.news_img' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<!-- <el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻浏览数量" prop="news_num">
<el-input-number v-model='formData.news_num'></el-input-number>
</el-form-item>
</el-col> -->
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="新闻内容" prop="news_content">
<RichText v-model='formData.news_content' :min-height="196"></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleAddClick(formRef)">添加</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { addNews, getDictionary } from "~/service/news";
import { useLoginStore } from "~/store";
// --
// --
//
const news_typee = ref([]);
async function get_news_typee() {
await getDictionary({ dictionary_value: 'news_typee' }).then((res) => {
news_typee.value = res
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 90;
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
const formData = reactive({});
const uoloadData = ref({
dirName: "News"
})
watch(props, (v) => {
dialogVisible.value = v.modelValue;
});
const rules = reactive({
news_title: [
{
required: true,
message: '新闻标题不能为空'
}
],
news_author: [
{
required: true,
message: '新闻作者不能为空'
}
],
news_intro: [
{
required: true,
message: '新闻简介不能为空'
}
],
news_type: [
{
required: true,
message: '新闻类型不能为空'
}
],
news_img: [
{
required: true,
message: '新闻封面不能为空'
}
],
news_time: [
{
required: true,
message: '新闻到期时间不能为空'
}
],
});
// --
//
const openDialog = () => {
get_news_typee()
};
const closeDialog = () => {
handleResetClick(formRef.value);
dialogVisible.value = false;
emits("update:modelValue", false);
};
const handleAddClick = async (formEl) => {
console.log(formData);
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await addNews(formData);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,110 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="新闻详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻标题" prop="news_title">
<el-input v-model='formData.news_title' type="text" placeholder='请输入新闻标题'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻作者" prop="news_author">
<el-input v-model='formData.news_author' type="text" placeholder='请输入新闻作者'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻简介" prop="news_intro">
<el-input v-model='formData.news_intro' type="textarea" placeholder='请输入新闻简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="新闻类型" prop="news_type" :label-width="labelWidth">
<el-select v-model="formData.news_type" clearable placeholder="请选择">
<el-option v-for="item in news_typee" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='新闻封面图片' prop='news_img'>
<UploadImage ref='uploadRef' v-model='formData.news_img' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻浏览数量:" prop="news_num">
<span>{{formData.news_num}}</span>
<!-- <el-input-number v-model='formData.news_num'></el-input-number> -->
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="新闻内容" prop="news_content">
<RichText v-model='formData.news_content'></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { isEmptyObject } from "~/utils/index";
import { getDictionary } from '~/service/news';
// --
// --
//
const news_typee = ref([]);
async function get_news_typee() {
await getDictionary({ dictionary_value: 'news_typee' }).then((res) => {
news_typee.value = res
})
}
// --
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
get_news_typee()
};
const closeDialog = () => {
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped></style>

View File

@ -1,184 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑新闻" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻标题" prop="news_title">
<el-input v-model='formData.news_title' type="text" placeholder='请输入新闻标题'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻作者" prop="news_author">
<el-input v-model='formData.news_author' type="text" placeholder='请输入新闻作者'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻简介" prop="news_intro">
<el-input v-model='formData.news_intro' type="textarea" placeholder='请输入新闻简介'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="新闻类型" prop="news_type" :label-width="labelWidth">
<el-select v-model="formData.news_type" clearable placeholder="请选择">
<el-option v-for="item in news_typee" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='新闻封面图片' prop='news_img'>
<UploadImage ref='uploadRef' v-model='formData.news_img' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="新闻浏览数量:" prop="news_num">
<span>{{formData.news_num}}</span>
<!-- <el-input-number v-model='formData.news_num'></el-input-number> -->
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="新闻内容" prop="news_content">
<RichText v-model='formData.news_content'></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick(formRef)">编辑</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { editNews, getDictionary } from "~/service/news";
import { useLoginStore } from "~/store";
// --
// --
//
const news_typee = ref([]);
async function get_news_typee() {
await getDictionary({ dictionary_value: 'news_typee' }).then((res) => {
news_typee.value = res
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
const uoloadData = ref({
dirName: "News"
})
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
get_news_typee()
};
const closeDialog = () => {
props.done();
emits("update:modelValue", false);
};
const rules = reactive({
news_title: [
{
required: true,
message: '新闻标题不能为空'
}
],
news_author: [
{
required: true,
message: '新闻作者不能为空'
}
],
news_intro: [
{
required: true,
message: '新闻简介不能为空'
}
],
news_type: [
{
required: true,
message: '新闻类型不能为空'
}
],
news_img: [
{
required: true,
message: '新闻封面不能为空'
}
],
news_time: [
{
required: true,
message: '新闻到期时间不能为空'
}
],
});
const handleEditClick = async (formEl) => {
console.log(formData.value);
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await editNews(formData.value);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,253 +0,0 @@
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>新闻管理</el-breadcrumb-item>
<el-breadcrumb-item to="/news/list">新闻列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="新闻标题">
<el-input v-model='params.news_title' placeholder='请输入新闻标题'></el-input>
</el-form-item>
<el-form-item label="新闻类型">
<el-select v-model="params.news_type" clearable placeholder="请选择">
<el-option v-for="item in news_typee" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加新闻 -->
<el-col :span="1">
<el-button type="primary" @click="addNewsDialogVisible = true"> 添加 </el-button>
</el-col>
<!-- 导出 -->
<el-button icon="ElIconDocument" @click="exportExcel(params)">导出</el-button>
<!-- 导入 -->
<el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
<el-button type="primary">导入</el-button>
</el-upload>
<!-- 下载导入模板 -->
<el-button icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button>
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
<el-button type="primary">
批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleDelete(selectionData)">
批量删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
<!-- 数据表格 -->
<DataTable ref="tableRef" style="width: 100%" :onSelectionChange="data => (selectionData = data)" :column="column"
:params="params" :request="params => getNewsList(params)">
<template #news_img="scope">
<el-image v-if="scope.row.news_img" :src="scope.row.news_img.split(',')[0]" lazy
:preview-src-list="scope.row.news_img.split(',')" :preview-teleported="true" :hide-on-click-modal="true"
fit="contain" class="el-avatar"></el-image>
<template v-else>暂无图片</template>
</template>
<template #news_type='scope'>
<dict-tag :options='news_typee' :value='scope.row.news_type' />
</template>
<template #chaoz="scope">
<el-space>
<el-button size="small" @click="handleUpdate(scope.row)">
编辑
</el-button>
<el-dropdown @command="handleCommand">
<el-button type="primary" size="small">
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{ type: 'detail', row: scope.row }">
详情
</el-dropdown-item>
<el-dropdown-item :command="{ type: 'delete', row: scope.row }">
删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</template>
</DataTable>
<!-- 添加新闻 -->
<AddNewsDialog v-model="addNewsDialogVisible" :done="() => tableRef.reload()"></AddNewsDialog>
<!-- 编辑新闻 -->
<EditNewsDialog v-model="EditNewsDialogVisible" :data="EditNewsDialogRow" :done="() => tableRef.reload()">
</EditNewsDialog>
<!-- 新闻详情 -->
<DetailNewsDialog v-model="DetailNewsDialogVisible" :data="DetailNewsDialogRow"></DetailNewsDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive } from 'vue';
import { useLoginStore } from "~/store";
import { getNewsList, deleteNews, getDictionary, exportExcel, downloadTemplate, importExcel } from '~/service/news';
import AddNewsDialog from './components/AddNewsDialog.vue';
import EditNewsDialog from './components/EditNewsDialog.vue';
import DetailNewsDialog from './components/DetailNewsDialog.vue';
const tableRef = ref();
const selectionData = ref([]);
const store = useLoginStore();
const addNewsDialogVisible = ref(false);
const EditNewsDialogVisible = ref(false);
const EditNewsDialogRow = ref({});
const DetailNewsDialogVisible = ref(false);
const DetailNewsDialogRow = ref({});
const headers = {
Accept: "application/json",
...store.headers,
};
//
const params = reactive({
news_title: "",
news_type: "",
});
const column = [
{
fixed: true,
type: 'selection'
},
{
prop: "news_title",
label: '新闻标题',
width: '150'
},
{
prop: "news_author",
label: '新闻作者',
width: '150'
},
{
prop: "news_intro",
label: '新闻简介',
width: '150'
},
{
prop: "news_type",
label: '新闻类型',
width: '150'
},
{
prop: "news_img",
label: '新闻封面',
width: '150'
},
{
prop: "news_num",
label: '新闻浏览数量',
width: '150'
},
{
label: '操作',
prop: 'chaoz',
width: '250'
}
];
const handleCommand = ({ type, row }) => {
switch (type) {
case "detail":
handleDetail(row);
break;
case 'delete':
handleDelete([row]);
break;
}
};
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该新闻吗?`).then(async () => {
const res = await deleteNews({
news_guid: data.map(v => v.news_guid).join()
});
if (res) {
tableRef.value.reload();
}
});
};
//
function handleUpdate(row) {
EditNewsDialogVisible.value = true
EditNewsDialogRow.value = row
}
//
function handleDetail(row) {
DetailNewsDialogVisible.value = true
DetailNewsDialogRow.value = row
}
//
let loadingImoprt = null;
const uploadLoading = () => {
loadingImoprt = ElLoading.service({
lock: true,
text: "正在导入中...",
background: "rgba(255, 255, 255, 0.7)",
});
};
const closeUploadLoading = () => loadingImoprt.close();
const handleExcelSuccess = (value) => {
if (value.code == 0) {
ElMessageBox.alert(value.msg, "导入信息", {
dangerouslyUseHTMLString: true,
confirmButtonText: "确定",
});
} else {
ElMessage.error(value.msg);
}
closeUploadLoading();
tableRef.value.reload();
};
//
const news_typee = ref([]);
async function get_news_typee() {
await getDictionary({ dictionary_value: 'news_typee' }).then((res) => {
news_typee.value = res
})
}
get_news_typee()
</script>

View File

@ -1,262 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="添加产品" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList" @change="getTempList()"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false, }"
placeholder="请选择上级菜单" v-model="formData.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="名称" prop="product_name">
<el-input v-model='formData.product_name' type="text" placeholder='请输入名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="价格" prop="product_price">
<el-input-number v-model='formData.product_price' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='图片' prop='product_img'>
<UploadImage ref='uploadRef' v-model='formData.product_img' :data=uoloadData :limit='5' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
<el-row style="margin: 0 20px;">
<span>产品参数</span>
<el-col class="por_tem_sty" :span='18'>
<!-- 新增自定义 -->
<el-form-item :label-width='labelWidth' label="自定义">
<el-input style="width: 40%;margin-right: 10px" v-model="productParamFormData.name"
placeholder='请输入产品参数名称'></el-input>
<el-input style="width: 40%;margin-right: 10px" v-model="productParamFormData.value"
placeholder='请输入产品参数内容'></el-input>
<el-button style="margin-left: 10px" :circle="true" icon="el-icon-plus"
@click="addProductParam()"></el-button>
</el-form-item>
<!-- 编辑 -->
<el-form-item v-for="(item, index) in formData.product_params" :key="index" :label-width='labelWidth'
:label="item.product_param_name">
<div style="display: flex">
<el-input v-model='item.product_param_value' :placeholder="'请输入' + item.product_param_name"></el-input>
<el-button style="margin-left: 10px" :circle="true" icon="el-icon-minus"
@click="deleteProductParam(index)"></el-button>
</div>
</el-form-item>
<el-button type="danger" style="width: 100%;" @click="deleteAllProductParam()">一键清空</el-button>
</el-col>
</el-row>
<el-row>
<el-col>
<el-form-item :label-width="labelWidth" label="详情" prop="product_details">
<RichText v-model='formData.product_details' :min-height='196'></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" :loading=isBtnLoading @click="handleAddClick(formRef)">添加</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { addProduct } from "~/service/product";
import { getProductTypeTree } from '~/service/product_type';
import { getProductParamTemplate } from '~/service/product_param';
import { useLoginStore } from "~/store";
// --
//
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
//
async function getTempList() {
if (formData.product_type_guid) {
getProductParamTemplate({ product_type_guid: formData.product_type_guid })
.then((res) => {
if (res.code == 0) {
formData.product_params = res.data;
}
})
}
}
const productParamFormData = reactive({});
const addProductParam = () => {
if (!formData.product_params) formData.product_params = [];
if (!productParamFormData.name || !productParamFormData.name.trim() || !productParamFormData.value || !productParamFormData.value.trim()) return;
formData.product_params.push({
product_param_name: productParamFormData.name,
product_param_value: productParamFormData.value
});
productParamFormData.name = null;
productParamFormData.value = null;
}
const deleteProductParam = (index) => {
formData.product_params.splice(index, 1);
}
const deleteAllProductParam = () => {
ElMessageBox.confirm(`您确定要一键清空产品参数吗?`).then(() => {
formData.product_params = [];
});
}
const verifyProductParam = () => {
let isSu = true;
if (formData.product_params) {
formData.product_params.some(item => {
if (!item.product_param_value || !item.product_param_value.trim()) {
ElMessage.error(`产品参数含有空值`)
isSu = false;
return true;
}
});
}
return isSu;
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 90;
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
const formData = reactive({});
const uoloadData = ref({
dirName: "Product"
})
watch(props, (v) => {
dialogVisible.value = v.modelValue;
});
const rules = reactive({
product_type_guid: [
{
required: true,
message: '产品系列不能为空'
}
],
product_name: [
{
required: true,
message: '名称不能为空'
}
],
product_img: [
{
required: true,
message: '图片不能为空'
}
],
product_details: [
{
required: true,
message: '详情不能为空'
}
],
product_price: [
{
required: true,
message: '价格不能为空'
}
],
});
// --
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
props.done();
handleResetClick(formRef.value);
dialogVisible.value = false;
emits("update:modelValue", false);
};
const isBtnLoading = ref(false);
const handleAddClick = async (formEl) => {
if (!formEl) return;
if (verifyProductParam() == false) return;
formEl.validate(async (valid) => {
if (!valid) return;
isBtnLoading.value = true;
const { code } = await addProduct(formData);
if (code == 0) {
closeDialog();
props.done();
}
isBtnLoading.value = false
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped>
.por_tem {
margin: 0 20px;
}
.por_tem_sty {
border: rgb(210, 208, 208) 1px solid;
padding: 15px;
border-radius: 10px;
margin: 25px 20px;
}
</style>

View File

@ -1,102 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="产品详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-input v-model='formData.product_type_name' type="text" placeholder='请输入产品系列'></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品名称" prop="product_name">
<el-input v-model='formData.product_name' type="text" placeholder='请输入产品名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品价格" prop="product_price">
<el-input-number v-model='formData.product_price' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='产品图片' prop='product_img'>
<UploadImage ref='uploadRef' v-model='formData.product_img' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col>
<el-form-item :label-width='labelWidth' label='产品参数' prop='product_img'>
<ElTag v-if="formData.product_params" v-for="(item, index) in formData.product_params" :key="index"
style="margin: 10px;" effect="light">
{{ item.product_param_name }}:{{ item.product_param_value }}
</ElTag>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="22">
<el-form-item :label-width="labelWidth" label="产品详情" prop="product_details">
<RichText v-model='formData.product_details' :min-height='196'></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { isEmptyObject } from "~/utils/index";
// --
// --
// --
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
};
const closeDialog = () => {
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped></style>

View File

@ -1,257 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑产品" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList" @change="getTempList()"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择上级菜单" v-model="formData.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="名称" prop="product_name">
<el-input v-model='formData.product_name' type="text" placeholder='请输入名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="价格" prop="product_price">
<el-input-number v-model='formData.product_price' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='图片' prop='product_img'>
<UploadImage ref='uploadRef' v-model='formData.product_img' :data=uoloadData :limit='5' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
<el-row style="margin: 0 20px;">
<span>产品参数</span>
<el-col class="por_tem_sty" :span='18'>
<!-- 新增自定义 -->
<el-form-item :label-width='labelWidth' label="自定义">
<el-input style="width: 40%;margin-right: 10px" v-model="productParamFormData.name"
placeholder='请输入产品参数名称'></el-input>
<el-input style="width: 40%;margin-right: 10px" v-model="productParamFormData.value"
placeholder='请输入产品参数内容'></el-input>
<el-button style="margin-left: 10px" :circle="true" icon="el-icon-plus"
@click="addProductParam()"></el-button>
</el-form-item>
<!-- 编辑 -->
<el-form-item v-for="(item, index) in formData.product_params" :key="index" :label-width='labelWidth'
:label="item.product_param_name">
<div style="display: flex">
<el-input v-model='item.product_param_value' :placeholder="'请输入' + item.product_param_name"></el-input>
<el-button style="margin-left: 10px" :circle="true" icon="el-icon-minus"
@click="deleteProductParam(index)"></el-button>
</div>
</el-form-item>
<el-button type="danger" style="width: 100%;" @click="deleteAllProductParam()">一键清空</el-button>
</el-col>
</el-row>
<el-row>
<el-col>
<el-form-item :label-width="labelWidth" label="详情" prop="product_details">
<RichText v-model='formData.product_details' :min-height='196'></RichText>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" :loading="isBtnLoading" @click="handleEditClick(formRef)">编辑</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { editProduct } from "~/service/product";
import { getProductTypeTree } from '~/service/product_type';
import { getProductParamTemplate } from '~/service/product_param';
import { useLoginStore } from "~/store";
// --
// --
//
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
//
async function getTempList() {
if (formData.value.product_type_guid) {
getProductParamTemplate({ product_type_guid: formData.value.product_type_guid })
.then((res) => {
if (res.code == 0) {
formData.value.product_params = res.data
}
})
}
}
const productParamFormData = reactive({});
const addProductParam = () => {
if (!formData.value.product_params) formData.value.product_params = [];
if (!productParamFormData.name || !productParamFormData.name.trim() || !productParamFormData.value || !productParamFormData.value.trim()) return;
formData.value.product_params.push({
product_param_name: productParamFormData.name,
product_param_value: productParamFormData.value
});
productParamFormData.name = null;
productParamFormData.value = null;
}
const deleteProductParam = (index) => {
formData.value.product_params.splice(index, 1);
}
const deleteAllProductParam = () => {
ElMessageBox.confirm(`您确定要一键清空产品参数吗?`).then(() => {
formData.value.product_params = [];
});
}
const verifyProductParam = () => {
let isSu = true;
if (formData.value.product_params) {
formData.value.product_params.some(item => {
if (!item.product_param_value || !item.product_param_value.trim()) {
ElMessage.error(`产品参数含有空值`)
isSu = false;
return true;
}
});
}
return isSu;
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
const uoloadData = ref({
dirName: "Product"
})
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
props.done();
emits("update:modelValue", false);
};
const rules = reactive({
product_type_guid: [
{
required: true,
message: '产品系列不能为空'
}
],
product_name: [
{
required: true,
message: '名称不能为空'
}
],
product_img: [
{
required: true,
message: '图片不能为空'
}
],
product_details: [
{
required: true,
message: '详情不能为空'
}
],
product_price: [
{
required: true,
message: '价格不能为空'
}
],
});
const isBtnLoading = ref(false);
const handleEditClick = async (formEl) => {
if (!formEl) return;
if (verifyProductParam() == false) return;
formEl.validate(async (valid) => {
if (!valid) return;
isBtnLoading.value = true
const { code } = await editProduct(formData.value);
if (code == 0) {
closeDialog();
props.done();
}
isBtnLoading.value = false
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped>
.por_tem_sty {
border: rgb(210, 208, 208) 1px solid;
padding: 15px;
border-radius: 10px;
margin: 25px 20px;
}
</style>

View File

@ -1,254 +0,0 @@
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>产品管理</el-breadcrumb-item>
<el-breadcrumb-item to="/product/list">产品列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品系列" clearable v-model="params.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
<el-form-item label="名称">
<el-input v-model='params.product_name' placeholder='请输入名称'></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加产品 -->
<el-col :span="1">
<el-button type="primary" @click="addProductDialogVisible = true" :done="() => tableRef.reload()"> 添加 </el-button>
</el-col>
<!-- 导出 -->
<!-- <el-button icon="ElIconDocument" @click="exportExcel(params)">导出</el-button> -->
<!-- 导入 -->
<!-- <el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
<el-button type="primary">导入</el-button>
</el-upload> -->
<!-- 下载导入模板 -->
<!-- <el-button icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button> -->
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
<el-button type="primary">
批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleDelete(selectionData)">
批量删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
<!-- 数据表格 -->
<DataTable ref="tableRef" style="width: 100%" :onSelectionChange="data => (selectionData = data)" :column="column"
:params="params" :request="params => getProductList(params)">
<template #product_params="scope">
<el-tag v-if="scope.row.product_params && scope.row.product_params.length"
v-for="(item, index) in scope.row.product_params" :key="index" style="margin: 5px;" effect="light">
{{ item.product_param_name }}:{{ item.product_param_value }}
</el-tag>
<el-tag type="info" v-else>未填写参数</el-tag>
</template>
<template #product_img="scope">
<el-image v-for="(item, index) in scope.row.product_img" :key="index" :src="item.url" lazy
:preview-src-list="scope.row.product_img" :preview-teleported="true" :hide-on-click-modal="true" fit="contain"
class="el-avatar"></el-image>
</template>
<template #chaoz="scope">
<el-space>
<el-button size="small" @click="handleUpdate(scope.row)">
编辑
</el-button>
<el-dropdown @command="handleCommand">
<el-button type="primary" size="small">
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{ type: 'detail', row: scope.row }">
详情
</el-dropdown-item>
<el-dropdown-item :command="{ type: 'delete', row: scope.row }">
删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</template>
</DataTable>
<!-- 添加产品 -->
<AddProductDialog v-model="addProductDialogVisible" :done="() => tableRef.reload()"></AddProductDialog>
<!-- 编辑产品 -->
<EditProductDialog v-model="EditProductDialogVisible" :data="EditProductDialogRow" :done="() => tableRef.reload()">
</EditProductDialog>
<!-- 产品详情 -->
<DetailProductDialog v-model="DetailProductDialogVisible" :data="DetailProductDialogRow"></DetailProductDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive } from 'vue';
import { useLoginStore } from "~/store";
import { getProductList, deleteProduct, exportExcel, downloadTemplate, importExcel } from '~/service/product';
import AddProductDialog from './components/AddProductDialog.vue';
import EditProductDialog from './components/EditProductDialog.vue';
import { getProductTypeTree } from '~/service/product_type';
import DetailProductDialog from './components/DetailProductDialog.vue';
const tableRef = ref();
const selectionData = ref([]);
const store = useLoginStore();
const addProductDialogVisible = ref(false);
const EditProductDialogVisible = ref(false);
const EditProductDialogRow = ref({});
const DetailProductDialogVisible = ref(false);
const DetailProductDialogRow = ref({});
const headers = {
Accept: "application/json",
...store.headers,
};
//
const params = reactive({
product_name: "",
product_type_guid: "",
});
const column = [
{
fixed: true,
type: 'selection'
},
{
prop: "product_type_name",
label: '产品系列',
width: '150'
},
{
prop: "product_name",
label: '产品名称',
width: '150'
},
{
prop: "product_img",
label: '产品图片',
width: '300'
},
{
prop: "product_params",
label: '产品参数',
width: '400'
},
{
prop: "product_price",
label: '产品价格',
width: '150'
},
{
label: '操作',
prop: 'chaoz',
fixed: 'right',
width: '250'
}
];
const handleCommand = ({ type, row }) => {
switch (type) {
case "detail":
handleDetail(row);
break;
case 'delete':
handleDelete([row]);
break;
}
};
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该产品吗?`).then(async () => {
const res = await deleteProduct({
product_guid: data.map(v => v.product_guid).join()
});
if (res) {
tableRef.value.reload();
}
});
};
//
function handleUpdate(row) {
EditProductDialogVisible.value = true
EditProductDialogRow.value = row
}
//
function handleDetail(row) {
DetailProductDialogVisible.value = true
DetailProductDialogRow.value = row
}
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
getList();
//
let loadingImoprt = null;
const uploadLoading = () => {
loadingImoprt = ElLoading.service({
lock: true,
text: "正在导入中...",
background: "rgba(255, 255, 255, 0.7)",
});
};
const closeUploadLoading = () => loadingImoprt.close();
const handleExcelSuccess = (value) => {
if (value.code == 0) {
ElMessageBox.alert(value.msg, "导入信息", {
dangerouslyUseHTMLString: true,
confirmButtonText: "确定",
});
} else {
ElMessage.error(value.msg);
}
closeUploadLoading();
tableRef.value.reload();
};
</script>

View File

@ -1,138 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="添加产品参数" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择上级菜单" clearable v-model="formData.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="参数名称" prop="product_param_name">
<el-input v-model='formData.product_param_name' type="text" placeholder='请输入产品参数名称'></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleAddClick(formRef)">添加</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { addProductParam } from "~/service/product_param";
import { getProductTypeTree } from '~/service/product_type';
import { useLoginStore } from "~/store";
// --
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
// --
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 90;
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
const formData = reactive({});
const uoloadData = ref({
dirName: "ProductParam"
})
watch(props, (v) => {
dialogVisible.value = v.modelValue;
});
const rules = reactive({
product_param_name: [
{
required: true,
message: '产品参数名称不能为空'
}
],
product_type_guid: [
{
required: true,
message: '产品系列不能为空'
}
],
});
// --
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
handleResetClick(formRef.value);
dialogVisible.value = false;
emits("update:modelValue", false);
};
const handleAddClick = async (formEl) => {
console.log(formData);
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await addProductParam(formData);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,133 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑产品参数" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择上级菜单" clearable v-model="formData.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="参数名称" prop="product_param_name">
<el-input v-model='formData.product_param_name' type="text" placeholder='请输入产品参数名称'></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick(formRef)">编辑</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { editProductParam } from "~/service/product_param";
import { getProductTypeTree } from '~/service/product_type';
import { useLoginStore } from "~/store";
// --
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
// --
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
const uoloadData = ref({
dirName: "ProductParam"
})
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
props.done();
emits("update:modelValue", false);
};
const rules = reactive({
product_param_name: [
{
required: true,
message: '产品参数名称不能为空'
}
],
product_type_guid: [
{
required: true,
message: '产品系列不能为空'
}
],
});
const handleEditClick = async (formEl) => {
console.log(formData.value);
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await editProductParam(formData.value);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,197 +0,0 @@
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>产品参数管理</el-breadcrumb-item>
<el-breadcrumb-item to="/product_param/list">产品参数列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="产品系列" prop="product_type_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品系列" clearable v-model="params.product_type_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加产品参数 -->
<el-col :span="1">
<el-button type="primary" @click="addProductParamDialogVisible = true"> 添加 </el-button>
</el-col>
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
<el-button type="primary">
批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleDelete(selectionData)">
批量删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
<!-- 数据表格 -->
<DataTable ref="tableRef" style="width: 100%" :onSelectionChange="data => (selectionData = data)" :column="column"
:params="params" :request="params => getProductParamList(params)">
<template #product_param_order="scope">
<el-input-number v-model='scope.row.product_param_order' controls-position="right" size="small"
@change="editProductParam(scope.row)"></el-input-number>
</template>
<template #chaoz="scope">
<el-space>
<el-button size="small" @click="handleUpdate(scope.row)">
编辑
</el-button>
<el-dropdown @command="handleCommand">
<el-button type="primary" size="small">
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{ type: 'detail', row: scope.row }">
详情
</el-dropdown-item>
<el-dropdown-item :command="{ type: 'delete', row: scope.row }">
删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</template>
</DataTable>
<!-- 添加产品参数 -->
<AddProductParamDialog v-model="addProductParamDialogVisible" :done="() => tableRef.reload()"></AddProductParamDialog>
<!-- 编辑产品参数 -->
<EditProductParamDialog v-model="EditProductParamDialogVisible" :data="EditProductParamDialogRow"
:done="() => tableRef.reload()"></EditProductParamDialog>
<!-- 产品参数详情 -->
<DetailProductParamDialog v-model="DetailProductParamDialogVisible" :data="DetailProductParamDialogRow">
</DetailProductParamDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive } from 'vue';
import { useLoginStore } from "~/store";
import { getProductParamList, editProductParam, deleteProductParam } from '~/service/product_param';
import { getProductTypeTree } from '~/service/product_type';
import AddProductParamDialog from './components/AddProductParamDialog.vue';
import EditProductParamDialog from './components/EditProductParamDialog.vue';
import DetailProductParamDialog from './components/DetailProductParamDialog.vue';
const tableRef = ref();
const selectionData = ref([]);
const store = useLoginStore();
const addProductParamDialogVisible = ref(false);
const EditProductParamDialogVisible = ref(false);
const EditProductParamDialogRow = ref({});
const DetailProductParamDialogVisible = ref(false);
const DetailProductParamDialogRow = ref({});
const headers = {
Accept: "application/json",
...store.headers,
};
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
getList();
//
const params = reactive({
product_type_guid: "",
});
const column = [
{
fixed: true,
type: 'selection'
},
{
prop: "product_param_name",
label: '产品参数名称',
width: '150'
},
{
prop: "product_type_name",
label: '产品系列',
width: '150'
},
{
prop: "product_param_order",
label: '参数排序',
width: '150'
},
{
label: '操作',
prop: 'chaoz',
fixed: 'right',
width: '250'
}
];
const handleCommand = ({ type, row }) => {
switch (type) {
case "detail":
handleDetail(row);
break;
case 'delete':
handleDelete([row]);
break;
}
};
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该产品参数吗?`).then(async () => {
const res = await deleteProductParam({
product_param_guid: data.map(v => v.product_param_guid).join()
});
if (res) {
tableRef.value.reload();
}
});
};
//
function handleUpdate(row) {
EditProductParamDialogVisible.value = true
EditProductParamDialogRow.value = row
}
//
function handleDetail(row) {
DetailProductParamDialogVisible.value = true
DetailProductParamDialogRow.value = row
}
</script>

View File

@ -1,169 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="添加产品系列" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="上级菜单" prop="product_type_parent_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择上级菜单" clearable v-model="formData.product_type_parent_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="系列标题" prop="product_type_name">
<el-input v-model='formData.product_type_name' placeholder='请输入系列标题'></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="排序" prop="product_type_order">
<el-input-number v-model='formData.product_type_order' controls-position='right'></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列图标' prop='product_type_icon'>
<UploadImage ref='uploadRef' v-model='formData.product_type_icon' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列封面' prop='product_type_cover'>
<UploadImage ref='uploadRef' v-model='formData.product_type_cover' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleAddClick(formRef)">添加</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { addProductType, getProductTypeTree } from "~/service/product_type";
import { useLoginStore } from "~/store";
// --
// --
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 90;
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
const formData = reactive({
product_type_parent_guid: '0',
product_type_order: 1,
});
const uoloadData = ref({
dirName: "ProductType"
})
watch(props, (v) => {
dialogVisible.value = v.modelValue;
});
const rules = reactive({
product_type_name: [
{
required: true,
message: '产品系列名称不能为空'
}
],
product_type_icon: [
{
required: true,
message: '产品系列图标不能为空'
}
],
product_type_cover: [
{
required: true,
message: '产品系列封面不能为空'
}
],
});
// --
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
handleResetClick(formRef.value);
dialogVisible.value = false;
emits("update:modelValue", false);
};
const handleAddClick = async (formEl) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await addProductType(formData);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,79 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="产品系列详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="系列标题" prop="product_type_name">
<el-input v-model='formData.product_type_name' type="text" placeholder='请输入系列标题'></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列图标' prop='product_type_icon'>
<UploadImage ref='uploadRef' v-model='formData.product_type_icon' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列封面' prop='product_type_cover'>
<UploadImage ref='uploadRef' v-model='formData.product_type_cover' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { isEmptyObject } from "~/utils/index";
// --
// --
// --
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
};
const closeDialog = () => {
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped></style>

View File

@ -1,163 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑产品系列" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :lg="24">
<el-form-item :label-width="labelWidth" label="上级菜单" prop="product_type_parent_guid">
<el-cascader class="w100" filterable :options="dataList"
:props="{ checkStrictly: true, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择上级菜单" clearable v-model="formData.product_type_parent_guid">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="系列标题" prop="product_type_name">
<el-input v-model='formData.product_type_name' type="text" placeholder='请输入系列标题'></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="排序" prop="product_type_order">
<el-input v-model='formData.product_type_order' type="number" placeholder='请输入排序'></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列图标' prop='product_type_icon'>
<UploadImage ref='uploadRef' v-model='formData.product_type_icon' :data=uoloadData :limit='1' :fileSize='1'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='系列封面' prop='product_type_cover'>
<UploadImage ref='uploadRef' v-model='formData.product_type_cover' :data=uoloadData :limit='1' :fileSize='1'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick(formRef)">编辑</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { editProductType, getProductTypeTree } from "~/service/product_type";
import { useLoginStore } from "~/store";
// --
// --
const dataList = ref();
async function getList() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
dataList.value = res.data
}
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
const uoloadData = ref({
dirName: "ProductType"
})
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
getList();
};
const closeDialog = () => {
props.done();
emits("update:modelValue", false);
};
const rules = reactive({
product_type_name: [
{
required: true,
message: '产品系列标题不能为空'
}
],
product_type_icon: [
{
required: true,
message: '产品系列图标不能为空'
}
],
product_type_cover: [
{
required: true,
message: '产品系列封面不能为空'
}
],
});
const handleEditClick = async (formEl) => {
console.log(formData.value);
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const { code } = await editProductType(formData.value);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,269 +0,0 @@
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>产品系列管理</el-breadcrumb-item>
<el-breadcrumb-item to="/product_type/list">产品系列列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="产品系列标题">
<el-input v-model='params.product_type_name' placeholder='请输入产品系列标题'></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getList()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加产品系列 -->
<el-col :span="1">
<el-button type="primary" @click="addProductTypeDialogVisible = true"> 添加 </el-button>
</el-col>
<!-- 导出 -->
<!-- <el-button icon="ElIconDocument" @click="exportExcel(params)">导出</el-button> -->
<!-- 导入 -->
<!-- <el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
<el-button type="primary">导入</el-button>
</el-upload> -->
<!-- 下载导入模板 -->
<!-- <el-button icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button> -->
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
<el-button type="primary">
批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleDelete(selectionData)">
批量删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
<!-- 数据表格 -->
<el-table v-loading="loading" :data="dataList" ref="tableRef" border highlight-current-row
:onSelectionChange="data => (selectionData = data)" :default-expand-all="tableExpandAll" row-key="product_type_guid"
:tree-props="{ children: 'children' }">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="product_type_name" width="200" label="产品系列名称" :show-overflow-tooltip="true"> </el-table-column>
<el-table-column prop="product_type_icon" width="200" label="产品系列图标" :show-overflow-tooltip="true">
<template #default="scope">
<el-image :src="scope.row.product_type_icon" :preview-src-list="[scope.row.product_type_icon]"
:preview-teleported="true"></el-image>
</template>
</el-table-column>
<el-table-column prop="product_type_cover" width="200" label="产品系列封面" :show-overflow-tooltip="true">
<template #default="scope">
<el-image :src="scope.row.product_type_cover" :preview-src-list="[scope.row.product_type_cover]"
:preview-teleported="true"></el-image>
</template>
</el-table-column>
<el-table-column prop="product_type_order" width="200" label="排序" sort>
<template #default="scope">
<el-input-number v-model='scope.row.product_type_order' controls-position="right"
@change="handleEditProductType(scope.row)"></el-input-number>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="250" fixed='right'>
<template #default="scope">
<el-button size="small" type="primary" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete([scope.row])">删除</el-button>
<el-button size="small" type="info" @click="handleDetail(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加产品系列 -->
<AddProductTypeDialog v-model="addProductTypeDialogVisible" :done="() => getList()"></AddProductTypeDialog>
<!-- 编辑产品系列 -->
<EditProductTypeDialog v-model="EditProductTypeDialogVisible" :data="EditProductTypeDialogRow" :done="() => getList()">
</EditProductTypeDialog>
<!-- 产品系列详情 -->
<DetailProductTypeDialog v-model="DetailProductTypeDialogVisible" :data="DetailProductTypeDialogRow">
</DetailProductTypeDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive, onMounted, watch } from 'vue';
import { useLoginStore } from "~/store";
import { getProductTypeTree, editProductType, deleteProductType, exportExcel, downloadTemplate, importExcel } from '~/service/product_type';
import AddProductTypeDialog from './components/AddProductTypeDialog.vue';
import EditProductTypeDialog from './components/EditProductTypeDialog.vue';
import DetailProductTypeDialog from './components/DetailProductTypeDialog.vue';
import createDraw from 'hyw-drag'
const tableRef = ref();
const tableKey = ref(0);
const selectionData = ref([]);
const store = useLoginStore();
const addProductTypeDialogVisible = ref(false);
const EditProductTypeDialogVisible = ref(false);
const EditProductTypeDialogRow = ref({});
const DetailProductTypeDialogVisible = ref(false);
const DetailProductTypeDialogRow = ref({});
const tableExpandAll = ref(false)
const headers = {
Accept: "application/json",
...store.headers,
};
//
const params = reactive({
product_type_name: "",
});
const column = [
{
fixed: true,
type: 'selection'
},
{
prop: "product_type_name",
label: '产品系列标题',
width: '150'
},
{
prop: "product_type_icon",
label: '产品系列图标',
width: '150'
},
{
prop: "product_type_cover",
label: '产品系列封面',
width: '150'
},
{
label: '操作',
prop: 'chaoz',
fixed: 'right',
width: '250'
}
];
const handleCommand = ({ type, row }) => {
switch (type) {
case "detail":
handleDetail(row);
break;
case 'delete':
handleDelete([row]);
break;
}
};
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该产品系列吗?`).then(async () => {
const res = await deleteProductType({
product_type_guid: data.map(v => v.product_type_guid).join()
});
if (res) {
getList();
}
});
};
//
function handleUpdate(row) {
EditProductTypeDialogVisible.value = true
EditProductTypeDialogRow.value = row
}
//
function handleDetail(row) {
DetailProductTypeDialogVisible.value = true
DetailProductTypeDialogRow.value = row
}
//
async function handleEditProductType(data) {
loading.value = true
await editProductType(data);
getList();
}
//
let loadingImoprt = null;
const uploadLoading = () => {
loadingImoprt = ElLoading.service({
lock: true,
text: "正在导入中...",
background: "rgba(255, 255, 255, 0.7)",
});
};
const closeUploadLoading = () => loadingImoprt.close();
const handleExcelSuccess = (value) => {
if (value.code == 0) {
ElMessageBox.alert(value.msg, "导入信息", {
dangerouslyUseHTMLString: true,
confirmButtonText: "确定",
});
} else {
ElMessage.error(value.msg);
}
closeUploadLoading();
tableRef.value.reload();
};
const loading = ref(false)
const dataList = ref([])
//
let drag = ref(false)
//
function getList() {
loading.value = true
getProductTypeTree(params).then((res) => {
if (res.code == 0) {
dataList.value = res.data
setTimeout(() => {
[...document.getElementsByClassName('el-table__row')].map(item => { item.classList.add('row1') });
[...document.getElementsByClassName('el-table__row--level-1')].map(item => { item.classList.remove('row1') })
drag.value === false && (drag.value = createDraw(document.getElementsByClassName('el-table__row')[0].parentElement))
})
loading.value = false
}
})
}
watch(drag, () => {
drag.value.start(() => {
dataList.value.map(item => {
tableRef.value.toggleRowExpansion(item, false)
})
tableExpandAll.value = false
})
drag.value.drop((info) => {
// console.log(info)
let targetIdx = [...document.getElementsByClassName('row1')].indexOf(info.el)
let sourceIdx = [...document.getElementsByClassName('row1')].indexOf(info.info.source.el)
let orderIdx = dataList.value[sourceIdx]['product_type_order']
dataList.value[targetIdx]['product_type_order'] = orderIdx
handleEditProductType(dataList.value[targetIdx])
})
})
getList()
</script>

View File

@ -1,65 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="班级详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级名称" prop="classes_name">
<el-input v-model='formData.classes_name' type="text" placeholder='请输入班级名称'></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { isEmptyObject } from "~/utils/index";
// --
// --
// --
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
// --
watch(props, (v) => {
formData.value = v.data;
});
//
const openDialog = () => {
};
const closeDialog = () => {
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped>
</style>

View File

@ -1,466 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="添加学生" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生名称" prop="student_name">
<el-input v-model='formData.student_name' type="text" placeholder='请输入学生名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="用户" prop="user_name">
<el-input v-model='formData.user_name' disabled type="text" placeholder='点击选择用户'>
<template #append>
<div @click="handleChooseUser">选择</div>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级" prop="classes_guid">
<el-select v-model="formData.classes_guid" clearable placeholder="请选择班级">
<el-option v-for="item in classesList" :label="item.classes_name" :key="item.classes_guid"
:value="item.classes_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="手机号" prop="studnet_phone">
<el-input v-model='formData.studnet_phone' type="text" placeholder='请输入手机号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="身份证号" prop="student_id_card">
<el-input v-model='formData.student_id_card' type="text" placeholder='请输入身份证号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="邮箱" prop="student_email">
<el-input v-model='formData.student_email' type="text" placeholder='请输入邮箱'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" :label-width="labelWidth" prop="student_sex">
<el-radio-group v-model="formData.student_sex" placeholder="请选择学生性别">
<el-radio v-for="item in sex" :key="item.dictionary_name" :label="item.dictionary_value">{{
item.dictionary_name
}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="价格/元" prop="student_price">
<el-input-number v-model='formData.student_price' :precision="2" :step="0.1"
:min="0"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="生日" prop="student_brithday">
<el-date-picker v-model="formData.student_brithday" type="date" value-format="YYYY-MM-DD"
placeholder="生日" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品类型" prop="product_type">
<el-cascader class="w100" :options="productTypeTreeList"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品类型" clearable v-model="formData.product_type" @change="clickProductTypeTree">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品" prop="product_guid">
<el-select v-model="formData.product_guid" clearable placeholder="请先选择产品类型" @change="clickProduct">
<el-option v-for="item in productList" :label="item.product_name" :key="item.product_guid"
:value="item.product_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品零件" prop="product_parts_guid">
<el-select v-model="formData.product_parts_guid" clearable placeholder="请先选择产品">
<el-option v-for="item in productPartsList" :label="item.product_parts_name"
:key="item.product_parts_guid" :value="item.product_parts_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生服务" prop="student_service">
<!-- <el-input v-model='formData.student_service' type="text" placeholder='请输入学生服务'></el-input> -->
<div v-for="(item, index) in formData.student_service" :key="index">
<div style="margin-left:10px">
{{ item.service_name + ":" + item.service_price + "元" }}
<el-button size="small" :circle="true" icon="el-icon-minus"
@click="handleCancel(index)"></el-button>
</div>
</div>
<el-button style="margin-left:10px" :circle="true" icon="el-icon-plus"
@click="handleStudentService"></el-button>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='头像图片' prop='student_img'>
<UploadImage ref='uploadRef' v-model='formData.student_img' :data=uoloadData :limit='1'
:fileSize='5' :drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='附件文件' prop='student_attachment'>
<UploadFile v-model='formData.student_attachment' :data=uoloadData />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='轮播图片图片' prop='student_banner_img'>
<UploadImage ref='uploadRef' v-model='formData.student_banner_img' :data=uoloadData :limit='5'
:fileSize='5' :drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="简介" prop="student_intro">
<RichText v-model='formData.student_intro'></RichText>
</el-form-item>
</el-col>
<el-col :span='24'>
<el-form-item :label-width='labelWidth' label='家庭住址' prop='student_location'>
<Map v-model='locationList' style='margin-top: 20px;'></Map>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会员类型" prop="student_membe_type">
<el-select v-model="formData.student_membe_type" clearable placeholder="请选择">
<el-option v-for="item in member_type" :label="item.dictionary_name"
:key="item.dictionary_value" :value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleAddClick(formRef)">添加</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
<!-- 学生服务 -->
<StudentServiceDialog v-model="StudentServiceDialogVisible"></StudentServiceDialog>
<!-- 选择用户 -->
<ChooseUserDialog v-model="ChooseUserDialogVisible"></ChooseUserDialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { addStudent, getDictionary, getClickProduct, getClickProductParts } from "~/service/student";
import { getClassesList } from '~/service/classes';
// import { getProductTypeTree } from "~/service/product_type";
import { useLoginStore } from "~/store";
import { validatePhTelNumber, validateIDCard, validateEmail } from '~/utils/validateRules';
import StudentServiceDialog from './StudentServiceDialog.vue';
import ChooseUserDialog from './ChooseUserDialog.vue';
// --
const locationList = ref({})
const classesList = ref([])
const productTypeTreeList = ref([]);
const productList = ref([]);
const productPartsList = ref([]);
const StudentServiceDialogVisible = ref({});
const ChooseUserDialogVisible = ref({});
// --
/**
* 打开学生服务弹窗
*/
const handleStudentService = () => {
StudentServiceDialogVisible.value = formData
}
/**
* 打开选择用户弹窗
*/
const handleChooseUser = () => {
ChooseUserDialogVisible.value = formData
}
/**
* 学生服务删除
*/
const handleCancel = function (index) {
const arr = formData.student_service;
arr.splice(index, 1);
ElMessage({
message: "删除成功",
type: "success",
});
};
/**
* 点击产品类型
*/
const clickProductTypeTree = () => {
getClickProductFun()
formData.product_guid = null
formData.product_parts_guid = null
productList.length = 0
productPartsList.length = 0
}
/**
* 点击产品
*/
const clickProduct = () => {
getClickProductPartsFun()
formData.product_parts_guid = null
productPartsList.length = 0
}
/**
* 获取班级列表
*/
async function getClassesListFun() {
getClassesList().then((res) => {
if (res.code == 0) {
classesList.value = res.data
}
})
}
/**
* 获取产品类型树形列表
*/
async function getProductTypeTreeFun() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
productTypeTreeList.value = res.data
}
})
}
/**
* 获取产品列表
*/
async function getClickProductFun() {
getClickProduct({ product_type_guid: formData.product_type }).then((res) => {
if (res.code == 0) {
productList.value = res.data
}
})
}
/**
* 获取产品零件列表
*/
async function getClickProductPartsFun() {
getClickProductParts({ product_guid: formData.product_guid }).then((res) => {
if (res.code == 0) {
productPartsList.value = res.data
}
})
}
//
const sex = ref([]);
async function get_sex() {
await getDictionary({ dictionary_value: 'sex' }).then((res) => {
sex.value = res
})
}
//
const member_type = ref([]);
async function get_member_type() {
await getDictionary({ dictionary_value: 'member_type' }).then((res) => {
member_type.value = res
})
}
//
const audit_status = ref([]);
async function get_audit_status() {
await getDictionary({ dictionary_value: 'audit_status' }).then((res) => {
audit_status.value = res
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 90;
const props = defineProps({
modelValue: Boolean,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
const formData = reactive({
student_name: ""
});
const uoloadData = ref({
dirName: "Student"
})
watch(props, (v) => {
dialogVisible.value = v.modelValue;
});
const rules = reactive({
student_name: [
{
required: true,
message: '学生名称不能为空'
}
],
user_name: [
{
required: true,
message: '用户不能为空'
}
],
classes_guid: [
{
required: true,
message: '班级不能为空'
}
],
studnet_phone: [
{
validator: validatePhTelNumber,
required: true,
}
],
student_id_card: [
{
validator: validateIDCard,
required: true,
}
],
student_email: [
{
validator: validateEmail,
}
],
student_sex: [
{
required: true,
message: '性别不能为空'
}
],
student_price: [
{
required: true,
message: '学生价格不能为空'
}
],
product_type: [
{
required: true,
message: '产品类型不能为空'
}
],
product_guid: [
{
required: true,
message: '产品不能为空'
}
],
product_parts_guid: [
{
required: true,
message: '产品零件不能为空'
}
],
student_img: [
{
required: true,
message: '头像不能为空'
}
],
student_intro: [
{
required: true,
message: '简介不能为空'
}
],
// student_location: [
// {
// required: true,
// message: ''
// }
// ],
});
// --
//
const openDialog = () => {
getClassesListFun()
getProductTypeTreeFun()
get_sex()
get_member_type()
get_audit_status()
};
const closeDialog = () => {
handleResetClick(formRef.value);
dialogVisible.value = false;
emits("update:modelValue", false);
};
const handleAddClick = async (formEl) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
//
if (!locationList.value.address) {
ElMessage.error("请选择学生家庭住址");
return
}
let locationData = locationList.value
formData.student_location = locationData.address
formData.longitude = locationData.longitude
formData.latitude = locationData.latitude
const { code } = await addStudent(formData);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,111 +0,0 @@
<template>
<el-dialog v-model="dialogVisible" title="选择用户" width="900px" @closed="closeDialog" @open="openDialog">
<el-form inline :model="params">
<el-form-item label="用户名称">
<el-input v-model='params.user' placeholder='请输入用户名称'></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<DataTable
ref="tableRef"
style="width: 100%"
:column="column"
:params="params"
:request="params => notBindUserList(params)"
highlight-current-row
@current-change="data => (selectionData = data)"
>
</DataTable>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick()">添加</el-button>
<el-button @click="handleResetClick()">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch, nextTick } from 'vue';
import { isEmptyObject, deepClone } from '~/utils/index';
import { ElMessage } from 'element-plus'
import { notBindUserList } from '~/service/student';
//
const total = ref(0)
const loading = ref(false)
//
const tableRef = ref(null);
const selectionData = ref([]);
//
const params = reactive({
user: "",
});
const emits = defineEmits(['update:modelValue']);
const dialogVisible = ref(false);
const props = defineProps({
modelValue: Object,
done: Function
});
const formData = ref({
...props.modelValue
});
const column = [
{
prop: "user_name",
label: '用户',
},
];
let userList = ref([]);
//
const openDialog = async () => {
}
watch(props, (v) => {
formData.value = v.modelValue;
dialogVisible.value = !isEmptyObject(v.modelValue);
});
// -
// -
const closeDialog = () => {
selectionData.value.length = 0
dialogVisible.value = false;
emits('update:modelValue', {});
};
//
const handleEditClick = async () => {
if (selectionData.value.length !== 0) {
let user_name = selectionData.value.user_name;
formData.value.user_name = user_name
if (formData.value.user_name != null) {
closeDialog();
}
} else {
ElMessage.error("请选择用户")
return;
}
};
const handleResetClick = async formEl => {
};
</script>

View File

@ -1,295 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="学生详情" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生名称" prop="student_name">
<el-input v-model='formData.student_name' type="text" placeholder='请输入学生名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="用户" prop="user_name">
<el-input v-model='formData.user_name' type="text" placeholder='请输入用户'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级" prop="classes_guid">
<el-select v-model="formData.classes_guid" clearable placeholder="请选择班级">
<el-option v-for="item in classesList" :label="item.classes_name" :key="item.classes_guid"
:value="item.classes_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="手机号" prop="studnet_phone">
<el-input v-model='formData.studnet_phone' type="text" placeholder='请输入手机号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="身份证号" prop="student_id_card">
<el-input v-model='formData.student_id_card' type="text" placeholder='请输入身份证号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="邮箱" prop="student_email">
<el-input v-model='formData.student_email' type="text" placeholder='请输入邮箱'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" :label-width="labelWidth" prop="student_sex">
<el-radio-group v-model="formData.student_sex" placeholder="请选择学生性别">
<el-radio v-for="item in sex" :key="item.dictionary_name" :label="item.dictionary_value">{{
item.dictionary_name
}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="价格/元" prop="student_price">
<el-input-number v-model='formData.student_price' :precision="2" :step="0.1"
:min="0"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="生日" prop="student_brithday">
<el-date-picker v-model="formData.student_brithday" type="date" value-format="YYYY-MM-DD"
placeholder="生日" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品类型" prop="product_type">
<el-cascader class="w100" :options="productTypeTreeList"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品类型" clearable v-model="formData.product_type" @change="clickProductTypeTree">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品" prop="product_guid">
<el-select v-model="formData.product_guid" clearable placeholder="请先选择产品类型" @change="clickProduct">
<el-option v-for="item in productList" :label="item.product_name" :key="item.product_guid"
:value="item.product_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品零件" prop="product_parts_guid">
<el-select v-model="formData.product_parts_guid" clearable placeholder="请先选择产品">
<el-option v-for="item in productPartsList" :label="item.product_parts_name"
:key="item.product_parts_guid" :value="item.product_parts_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生服务" prop="student_service">
<div v-for="(item, index) in formData.student_service" :key="index">
<div style="margin-left:10px">
{{ item.service_name + ":" + item.service_price + "元" }}
</div>
</div>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='头像图片' prop='student_img'>
<UploadImage ref='uploadRef' v-model='formData.student_img' :limit='1'
:fileSize='5' :drag='true' :isShowTip='false' :isDisabled="true" />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='附件文件' prop='student_attachment'>
<UploadFile v-model='formData.student_attachment' :isDetail="true" />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='轮播图片图片' prop='student_banner_img'>
<UploadImage ref='uploadRef' v-model='formData.student_banner_img' :limit='5'
:fileSize='5' :drag='true' :isShowTip='false' :isDisabled="true" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="简介" prop="student_intro">
<RichText v-model='formData.student_intro'></RichText>
</el-form-item>
</el-col>
<el-col :span='24'>
<el-form-item :label-width='labelWidth' label='家庭住址' prop='student_location'>
<Map v-model='locationList' style='margin-top: 20px;' :isClick="false"></Map>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会员类型" :label-width="labelWidth" prop="student_membe_type">
<dict-tag :options="member_type" :value="formData.student_membe_type" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="会员时间" prop="student_member_begin_time">
<el-date-picker disabled v-model="formData.student_member_time" type="daterange"
value-format="YYYY-MM-DD" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审核状态" :label-width="labelWidth" prop="student_audit_status">
<dict-tag :options="audit_status" :value="formData.student_audit_status" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="审核人" prop="student_audit_user_guid">
{{ formData.student_audit_user_name }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { isEmptyObject } from "~/utils/index";
import { getDictionary ,getClickProduct, getClickProductParts } from "~/service/student";
import { getClassesList } from '~/service/classes';
// import { getProductTypeTree } from "~/service/product_type";
import StudentServiceDialog from './StudentServiceDialog.vue';
// --
const locationList = ref({})
const classesList = ref([])
const productTypeTreeList = ref([]);
const productList = ref([]);
const productPartsList = ref([]);
const StudentServiceDialogVisible = ref({});
// --
/**
* 打开学生服务弹窗
*/
const handleStudentService = () => {
StudentServiceDialogVisible.value = formData
}
/**
* 获取班级列表
*/
async function getClassesListFun() {
getClassesList().then((res) => {
if (res.code == 0) {
classesList.value = res.data
}
})
}
/**
* 获取产品类型树形列表
*/
async function getProductTypeTreeFun() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
productTypeTreeList.value = res.data
}
})
}
/**
* 获取产品列表
*/
async function getClickProductFun() {
getClickProduct({ product_type_guid: formData.value.product_type }).then((res) => {
if (res.code == 0) {
productList.value = res.data
}
})
}
/**
* 获取产品零件列表
*/
async function getClickProductPartsFun() {
getClickProductParts({ product_guid: formData.value.product_guid }).then((res) => {
if (res.code == 0) {
productPartsList.value = res.data
}
})
}
//
const sex = ref([]);
async function get_sex() {
await getDictionary({ dictionary_value: 'sex' }).then((res) => {
sex.value = res
})
}
//
const member_type = ref([]);
async function get_member_type() {
await getDictionary({ dictionary_value: 'member_type' }).then((res) => {
member_type.value = res
})
}
//
const audit_status = ref([]);
async function get_audit_status() {
await getDictionary({ dictionary_value: 'audit_status' }).then((res) => {
audit_status.value = res
})
}
// --
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
// --
watch(props, (v) => {
formData.value = v.data;
if (formData.value.longitude) {
locationList.value.address = formData.value.student_location;
locationList.value.longitude = formData.value.longitude;
locationList.value.latitude = formData.value.latitude;
}
});
//
const openDialog = () => {
getClickProductFun()
getClickProductPartsFun()
getClassesListFun()
getProductTypeTreeFun()
get_sex()
get_member_type()
get_audit_status()
};
const closeDialog = () => {
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped></style>

View File

@ -1,510 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="编辑学生" width="900px" @closed="closeDialog" @open="openDialog">
<el-form ref="formRef" :model="formData" :rules="rules">
<el-row>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生名称" prop="student_name">
<el-input v-model='formData.student_name' type="text" placeholder='请输入学生名称'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="用户" prop="user_guid">
<el-input v-model='formData.user_name' disabled type="text" placeholder='请输入用户'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="班级" prop="classes_guid">
<el-select v-model="formData.classes_guid" clearable placeholder="请选择班级">
<el-option v-for="item in classesList" :label="item.classes_name" :key="item.classes_guid"
:value="item.classes_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="手机号" prop="studnet_phone">
<el-input v-model='formData.studnet_phone' type="text" placeholder='请输入手机号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="身份证号" prop="student_id_card">
<el-input v-model='formData.student_id_card' type="text" placeholder='请输入身份证号'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="邮箱" prop="student_email">
<el-input v-model='formData.student_email' type="text" placeholder='请输入邮箱'></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" :label-width="labelWidth" prop="student_sex">
<el-radio-group v-model="formData.student_sex" placeholder="请选择学生性别">
<el-radio v-for="item in sex" :key="item.dictionary_name" :label="item.dictionary_value">{{
item.dictionary_name
}}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="价格/元" prop="student_price">
<el-input-number v-model='formData.student_price' :precision="2" :step="0.1" :min="0"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="生日" prop="student_brithday">
<el-date-picker v-model="formData.student_brithday" type="date" value-format="YYYY-MM-DD" placeholder="生日" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品类型" prop="product_type">
<el-cascader class="w100" :options="productTypeTreeList"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品类型" clearable v-model="formData.product_type" @change="clickProductTypeTree">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品" prop="product_guid">
<el-select v-model="formData.product_guid" clearable placeholder="请先选择产品类型" @change="clickProduct">
<el-option v-for="item in productList" :label="item.product_name" :key="item.product_guid"
:value="item.product_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="产品零件" prop="product_parts_guid">
<el-select v-model="formData.product_parts_guid" clearable placeholder="请先选择产品">
<el-option v-for="item in productPartsList" :label="item.product_parts_name" :key="item.product_parts_guid"
:value="item.product_parts_guid"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="学生服务" prop="student_service">
<!-- <el-input v-model='formData.student_service' type="text" placeholder='请输入学生服务'></el-input> -->
<!-- {{ formData.student_service }} -->
<div v-for="(item, index) in formData.student_service" :key="index">
<div style="margin-left:10px">
{{ item.service_name + ":" + item.service_price + "元" }}
<el-button size="small" :circle="true" icon="el-icon-minus" @click="handleCancel(index)"></el-button>
</div>
</div>
<el-button style="margin-left:10px" :circle="true" icon="el-icon-plus"
@click="handleStudentService"></el-button>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='头像图片' prop='student_img'>
<UploadImage ref='uploadRef' v-model='formData.student_img' :data=uoloadData :limit='1' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='附件文件' prop='student_attachment'>
<UploadFile v-model='formData.student_attachment' :data=uoloadData />
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item :label-width='labelWidth' label='轮播图片图片' prop='student_banner_img'>
<UploadImage ref='uploadRef' v-model='formData.student_banner_img' :data=uoloadData :limit='5' :fileSize='5'
:drag='true' :isShowTip='false' />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="简介" prop="student_intro">
<RichText v-model='formData.student_intro'></RichText>
</el-form-item>
</el-col>
<el-col :span='24'>
<el-form-item :label-width='labelWidth' label='家庭住址' prop='student_location'>
<Map v-model='locationList' style='margin-top: 20px;'></Map>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会员类型" :label-width="labelWidth" prop="student_membe_type">
<dict-tag :options="member_type" :value="formData.student_membe_type" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item :label-width="labelWidth" label="会员时间" prop="student_member_time">
<el-date-picker v-model="formData.student_member_time" type="daterange" value-format="YYYY-MM-DD"
range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="hanleChangeTime" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审核状态" :label-width="labelWidth" prop="student_audit_status">
<dict-tag :options="audit_status" :value="formData.student_audit_status" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label-width="labelWidth" label="审核人" prop="student_audit_user_guid">
{{ formData.student_audit_user_name }}
</el-form-item>
</el-col>
<!-- <div class="box_pos">
<div class="box">
<input type="text" @change="request()">
<div :v-model="isShow" :data="dataList"></div>
</div>
</div>
const searchData = []
request(){
//..
searchData.value = res
} -->
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick(formRef)">编辑</el-button>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
<!-- 学生服务 -->
<StudentServiceDialog v-model="StudentServiceDialogVisible"></StudentServiceDialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import { editStudent, getDictionary, getClickProduct, getClickProductParts } from "~/service/student";
import { getClassesList } from '~/service/classes';
// import { getProductTypeTree } from "~/service/product_type";
import { useLoginStore } from "~/store";
import { validatePhTelNumber, validateIDCard, validateEmail } from '~/utils/validateRules';
import StudentServiceDialog from './StudentServiceDialog.vue';
// --
const locationList = ref({})
const classesList = ref([])
const productTypeTreeList = ref([]);
const productList = ref([]);
const productPartsList = ref([]);
const StudentServiceDialogVisible = ref({});
// --
//
function hanleChangeTime(val) {
formData.value.service_begin_time = val[0]
formData.value.service_end_time = val[1]
let time = TimestampToDate2()
console.log(time);
if (val[0] < time) {
ElMessage.error("不能选择小于当前时间的日期!")
formData.value.student_member_time.length = 0
}
}
function TimestampToDate2() {
let now = new Date(),
y = now.getFullYear(),
m = now.getMonth() + 1,
d = now.getDate();
return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d);
}
const request = () =>{
getClickProduct({ product_type_guid: formData.value.product_type }).then((res) => {
if (res.code == 0) {
if(res.data.length == 0) return
dataList.value = res.data
}
})
}
/**
* 打开学生服务弹窗
*/
const handleStudentService = () => {
StudentServiceDialogVisible.value = formData.value
}
/**
* 学生服务删除
*/
const handleCancel = function (index) {
let arr = Object.values(formData.value.student_service);
arr.splice(index, 1);
formData.value.student_service = arr
ElMessage({
message: "删除成功",
type: "success",
});
};
/**
* 点击产品类型
*/
const clickProductTypeTree = () => {
getClickProductFun()
formData.value.product_guid = null
formData.value.product_parts_guid = null
productList.length = 0
productPartsList.length = 0
}
/**
* 点击产品
*/
const clickProduct = () => {
getClickProductPartsFun()
formData.value.product_parts_guid = null
productPartsList.length = 0
}
/**
* 获取班级列表
*/
async function getClassesListFun() {
getClassesList().then((res) => {
if (res.code == 0) {
classesList.value = res.data
}
})
}
/**
* 获取产品类型树形列表
*/
async function getProductTypeTreeFun() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
productTypeTreeList.value = res.data
}
})
}
/**
* 获取产品列表
*/
async function getClickProductFun() {
getClickProduct({ product_type_guid: formData.value.product_type }).then((res) => {
if (res.code == 0) {
productList.value = res.data
}
})
}
/**
* 获取产品零件列表
*/
async function getClickProductPartsFun() {
getClickProductParts({ product_guid: formData.value.product_guid }).then((res) => {
if (res.code == 0) {
productPartsList.value = res.data
}
})
}
//
const sex = ref([]);
async function get_sex() {
await getDictionary({ dictionary_value: 'sex' }).then((res) => {
sex.value = res
})
}
//
const member_type = ref([]);
async function get_member_type() {
await getDictionary({ dictionary_value: 'member_type' }).then((res) => {
member_type.value = res
})
}
//
const audit_status = ref([]);
async function get_audit_status() {
await getDictionary({ dictionary_value: 'audit_status' }).then((res) => {
audit_status.value = res
})
}
// --
const store = useLoginStore();
const headers = {
Accept: "application/json",
...store.headers,
};
const formRef = ref();
const labelWidth = 100;
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const formData = ref({
...props.data,
});
const uoloadData = ref({
dirName: "Student"
})
// --
watch(props, (v) => {
formData.value = v.data;
if (formData.value.longitude) {
locationList.value.address = formData.value.student_location;
locationList.value.longitude = formData.value.longitude;
locationList.value.latitude = formData.value.latitude;
}
});
//
const openDialog = () => {
getClickProductFun()
getClickProductPartsFun()
getClassesListFun()
getProductTypeTreeFun()
get_sex()
get_member_type()
get_audit_status()
};
const closeDialog = () => {
props.done();
emits("update:modelValue", false);
};
const rules = reactive({
student_name: [
{
required: true,
message: '学生名称不能为空'
}
],
user_guid: [
{
required: true,
message: '用户不能为空'
}
],
classes_guid: [
{
required: true,
message: '班级不能为空'
}
],
studnet_phone: [
{
validator: validatePhTelNumber,
required: true,
}
],
student_id_card: [
{
validator: validateIDCard,
required: true,
}
],
student_email: [
{
validator: validateEmail,
}
],
student_sex: [
{
required: true,
message: '性别不能为空'
}
],
student_price: [
{
required: true,
message: '学生价格不能为空'
}
],
product_type: [
{
required: true,
message: '产品类型不能为空'
}
],
product_guid: [
{
required: true,
message: '产品不能为空'
}
],
product_parts_guid: [
{
required: true,
message: '产品零件不能为空'
}
],
student_img: [
{
required: true,
message: '头像不能为空'
}
],
student_intro: [
{
required: true,
message: '简介不能为空'
}
],
});
const handleEditClick = async (formEl) => {
if (formData.value.student_member_time.length == 0) return ElMessage.error("请选择会员时间!")
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) {
return;
}
//
if (!locationList.value.address) {
ElMessage.error("请选择学生家庭住址");
return
}
let locationData = locationList.value
formData.value.student_location = locationData.address
formData.value.longitude = locationData.longitude
formData.value.latitude = locationData.latitude
const { code } = await editStudent(formData.value);
if (code == 0) {
closeDialog();
props.done();
}
});
};
const handleResetClick = async (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
<style lang="less" scoped></style>

View File

@ -1,48 +0,0 @@
<template>
<el-dialog v-model="props.modelValue" title="导入信息" width="400px" @closed="closeDialog" @open="openDialog">
{{ formData }}
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
// --
// --
// --
const formData = ref({
...props.data,
});
const props = defineProps({
modelValue: Boolean,
data: Object,
done: Function,
});
const emits = defineEmits(["update:modelValue"]);
const dialogVisible = ref(props.modelValue);
watch(props, (v) => {
formData.value = v.data;
console.log(formData.value);
});
// --
//
const openDialog = () => {
};
const closeDialog = () => {
dialogVisible.value = false;
emits("update:modelValue", false);
};
</script>
<style lang="less" scoped></style>

View File

@ -1,121 +0,0 @@
<template>
<el-dialog
v-model="dialogVisible"
title="学生服务"
width="400px"
@closed="closeDialog"
>
<el-form
ref="formRef"
:model="formData"
>
<el-form-item :label-width="labelWidth" label="服务类型" prop="">
<el-input
v-model="serviceList.service_name"
type="text"
placeholder="请输入服务类型"
></el-input>
</el-form-item>
<el-form-item :label-width="labelWidth" label="价格" prop="">
<el-input
v-model="serviceList.service_price"
placeholder="请输入价格"
type="number"
><template #append></template></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="handleEditClick(formRef)"
>添加</el-button
>
<el-button @click="handleResetClick(formRef)">重置</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { reactive, ref, watch } from 'vue';
import { isEmptyObject,deepClone } from '~/utils/index';
import { ElMessage } from 'element-plus'
//
const formRef = ref();
const labelWidth = 100;
const serviceList = ref({
service_name: "",
service_price: ""
});
//
const emits = defineEmits(['update:modelValue']);
const dialogVisible = ref(false);
const props = defineProps({
modelValue: Object,
done: Function
});
const formData = ref({
...props.modelValue
});
watch(props, (v) => {
formData.value = v.modelValue;
dialogVisible.value = !isEmptyObject(v.modelValue);
});
// -
// -
const closeDialog = () => {
handleResetClick(formRef.value);
dialogVisible.value = false;
emits('update:modelValue', {});
};
//
const handleEditClick = async (formEl) => {
if (!formEl) return;
if(serviceList.value.service_name == "" || serviceList.value.service_price == ""){
ElMessage({
message: '请填写服务类型和价格',
type: 'error',
})
return;
}
formEl.validate(async (valid) => {
if (!valid) {
return;
}
const obj = formData.value.student_service;
console.log(obj);
var arr = []
for (let i in obj) {
arr.push(obj[i]); //
}
console.log(arr,"原来的");
let newObj = deepClone(serviceList.value);
arr.push(newObj)
// let newObj = deepClose(serviceList.value);
// arr.push(newObj)
console.log(arr,"后面的");
formData.value.student_service = arr
if(formData.value.student_service != null){
serviceList.value.service_name = null
serviceList.value.service_price = null
closeDialog();
}
});
};
const handleResetClick = async formEl => {
if (!formEl) return;
formEl.resetFields();
};
</script>

View File

@ -1,650 +0,0 @@
<template>
<!-- 面包屑 -->
<el-breadcrumb>
<el-breadcrumb-item>学生管理</el-breadcrumb-item>
<el-breadcrumb-item to="/student/list">学生列表</el-breadcrumb-item>
</el-breadcrumb>
<el-row>
<el-col :span="4">
<el-tree :data="treeData" :props="{
label: 'name',
}" node-key="id" :default-expand-all="false" @node-click="handleNodeClick" highlight-current
:expand-on-click-node="false" />
</el-col>
<el-col :span="20">
<!-- 搜索 -->
<el-form inline :model="params">
<el-form-item label="学生名称">
<el-input v-model='params.student_name' placeholder='请输入学生名称'></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model='params.studnet_phone' placeholder='请输入手机号'></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input v-model='params.student_id_card' placeholder='请输入身份证号'></el-input>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model='params.student_email' placeholder='请输入邮箱'></el-input>
</el-form-item>
<el-form-item label="性别">
<el-select v-model="params.student_sex" clearable placeholder="请选择">
<el-option v-for="item in sex" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="产品类型">
<el-cascader class="w100" :options="productTypeTreeList" :show-all-levels="false"
:props="{ checkStrictly: false, value: 'product_type_guid', label: 'product_type_name', emitPath: false }"
placeholder="请选择产品类型" clearable v-model="params.product_type" @change="clickProductTypeTree">
<template #default="{ node, data }">
<span>{{ data.product_type_name }}</span>
<span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
</template>
</el-cascader>
</el-form-item>
<el-form-item label="产品">
<el-select v-model="params.product_guid" clearable placeholder="请先选择产品类型" @change="clickProduct">
<el-option v-for="item in productList" :label="item.product_name" :key="item.product_guid"
:value="item.product_guid"></el-option>
</el-select>
</el-form-item>
<el-form-item label="产品零件" prop="product_parts_guid">
<el-select v-model="params.product_parts_guid" clearable placeholder="请先选择产品">
<el-option v-for="item in productPartsList" :label="item.product_parts_name" :key="item.product_parts_guid"
:value="item.product_parts_guid"></el-option>
</el-select>
</el-form-item>
<el-form-item label="会员类型">
<el-select v-model="params.student_membe_type" clearable placeholder="请选择">
<el-option v-for="item in member_type" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="审核状态">
<el-select v-model="params.student_audit_status" clearable placeholder="请选择">
<el-option v-for="item in audit_status" :key="item.dictionary_guid" :label="item.dictionary_name"
:value="item.dictionary_value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="会员日期">
<el-date-picker v-model="params.student_member_time" style="width: 240px" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD">
</el-date-picker>
</el-form-item>
<el-form-item label="生日">
<el-date-picker v-model="params.student_brithday" style="width: 240px" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="tableRef.reload()" icon="ElIconSearch">
搜索
</el-button>
</el-form-item>
</el-form>
<el-space style="margin-bottom: 10px;">
<!-- 添加学生 -->
<el-col :span="1">
<el-button type="primary" @click="addStudentDialogVisible = true"> 添加 </el-button>
</el-col>
<!-- 导出 -->
<el-button icon="ElIconDocument" @click="exportExcel()">导出</el-button>
<!-- 导入 -->
<el-upload class="upload-demo" :action="importExcel" :headers="headers" :on-success="handleExcelSuccess"
:on-progress="uploadLoading" :on-error="closeUploadLoading" style="margin-left: 10px" :show-file-list="false">
<el-button type="primary">导入</el-button>
</el-upload>
<!-- 下载导入模板 -->
<el-button icon="ElIconDownload" @click="downloadTemplate()">下载导入模板</el-button>
<!-- 下拉操作 -->
<el-dropdown v-if="selectionData.length">
<el-button type="primary">
批量操作<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleDelete(selectionData)">
批量删除
</el-dropdown-item>
<el-dropdown-item @click="handleAudit(selectionData)">
批量审批
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
<!-- 数据表格 -->
<DataTable ref="tableRef" style="width: 100%" :onSelectionChange="data => (selectionData = data)" :column="column"
:params="params" :request="params => getStudentList(params)">
<template #student_img="scope">
<el-image v-if="scope.row.student_img" :src="scope.row.student_img.split(',')[0]" lazy
:preview-src-list="scope.row.student_img.split(',')" :preview-teleported="true" :hide-on-click-modal="true"
fit="contain" class="el-avatar"></el-image>
<template v-else>暂无图片</template>
</template>
<template #student_banner_img="scope">
<el-image v-if="scope.row.student_banner_img" :src="scope.row.student_banner_img.split(',')[0]" lazy
:preview-src-list="scope.row.student_banner_img.split(',')" :preview-teleported="true"
:hide-on-click-modal="true" fit="contain" class="el-avatar"></el-image>
<template v-else>暂无图片</template>
</template>
<template #student_service="scope">
<div v-for="(item, index) in scope.row.student_service " :key="index">
<span>{{ item.service_name + "" + item.service_price + "元" }}</span>
</div>
</template>
<template #student_sex="scope">
<dict-tag :options="sex" :value="scope.row.student_sex" />
</template>
<template #student_membe_type="scope">
<dict-tag :options="member_type" :value="scope.row.student_membe_type" />
</template>
<template #student_audit_status="scope">
<dict-tag :options="audit_status" :value="scope.row.student_audit_status" />
</template>
<template #chaoz="scope">
<el-space>
<el-button v-if="scope.row.student_audit_status == 2" size="small" @click="handleUpdate(scope.row)">
编辑
</el-button>
<el-button v-if="scope.row.student_audit_status == 1" size="small" type="warning" @click="handleAudit(scope.row)">
审核
</el-button>
<el-dropdown @command="handleCommand">
<el-button type="primary" size="small">
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{ type: 'detail', row: scope.row }">
详情
</el-dropdown-item>
<el-dropdown-item :command="{ type: 'delete', row: scope.row }">
删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-space>
</template>
</DataTable>
</el-col>
</el-row>
<!-- 添加学生 -->
<AddStudentDialog v-model="addStudentDialogVisible" :done="() => tableRef.reload()"></AddStudentDialog>
<!-- 编辑学生 -->
<EditStudentDialog v-model="EditStudentDialogVisible" :data="EditStudentDialogRow" :done="() => tableRef.reload()">
</EditStudentDialog>
<!-- 学生详情 -->
<DetailStudentDialog v-model="DetailStudentDialogVisible" :data="DetailStudentDialogRow"></DetailStudentDialog>
<!-- 导入提示框 -->
<ImportMsgDialog v-model="ImportMsgDialogVisible" :data="ImportMsgDialogRow" :done="() => tableRef.reload()">
</ImportMsgDialog>
</template>
<script setup>
import { ArrowDown } from '@element-plus/icons-vue';
import { ref, reactive, watch } from 'vue';
import { useLoginStore } from "~/store";
import { changeDataPropertyName } from "~/utils/index";
import { getStudentList, deleteStudent, getDictionary, exportExcel, downloadTemplate, importExcel, getClickProduct, getClickProductParts, getProductTree ,auditStudent} from '~/service/student';
// import { getProductTypeTree } from "~/service/product_type";
import AddStudentDialog from './components/AddStudentDialog.vue';
import EditStudentDialog from './components/EditStudentDialog.vue';
import DetailStudentDialog from './components/DetailStudentDialog.vue';
import ImportMsgDialog from './components/ImportMsgDialog.vue';
import { ElMessage } from 'element-plus';
const tableRef = ref();
const selectionData = ref([]);
const store = useLoginStore();
const addStudentDialogVisible = ref(false);
const EditStudentDialogVisible = ref(false);
const EditStudentDialogRow = ref({});
const DetailStudentDialogVisible = ref(false);
const DetailStudentDialogRow = ref({});
const ImportMsgDialogVisible = ref(false);
const ImportMsgDialogRow = ref({});
const productTypeTreeList = ref([]);
const productList = ref([]);
const productPartsList = ref([]);
const treeData = ref([]);
const headers = {
Accept: "application/json",
...store.headers,
};
//
const params = reactive({
student_name: "",
studnet_phone: "",
student_id_card: "",
student_email: "",
student_sex: "",
student_membe_type: "",
student_audit_status: "",
product_type: "",
product_guid: "",
product_parts_guid: "",
student_member_time: "",
student_brithday: "",
});
const column = [
{
fixed: true,
type: 'selection'
},
{
prop: "student_name",
label: '学生名称',
width: '150'
},
{
prop: "user_name",
label: '用户',
width: '150'
},
{
prop: "classes_name",
label: '班级',
width: '150'
},
{
prop: "student_img",
label: '头像',
width: '150'
},
{
prop: "studnet_phone",
label: '手机号',
width: '150'
},
{
prop: "student_id_card",
label: '身份证号',
width: '150'
},
{
prop: "student_email",
label: '邮箱',
width: '150'
},
{
prop: "student_sex",
label: '性别',
width: '150'
},
{
prop: "student_price",
label: '学生价格',
width: '150'
},
{
prop: "student_brithday",
label: '生日',
width: '150'
},
{
prop: "product_type_name",
label: '产品类型',
width: '150'
},
{
prop: "product_name",
label: '产品',
width: '150'
},
{
prop: "product_parts_name",
label: '产品零件',
width: '150'
},
{
prop: "student_service",
label: '学生服务',
width: '150'
},
{
prop: "student_banner_img",
label: '轮播图片',
width: '150'
},
{
prop: "student_location",
label: '家庭住址',
width: '150'
},
{
prop: "student_membe_type",
label: '会员类型',
width: '150'
},
{
prop: "student_member_begin_time",
label: '会员开始时间',
width: '150'
},
{
prop: "student_member_end_time",
label: '会员结束时间',
width: '150'
},
{
prop: "student_audit_status",
label: '审核状态',
width: '150'
},
{
prop: "student_audit_user_name",
label: '审核人',
width: '150'
},
{
label: '操作',
prop: 'chaoz',
width: '250'
}
];
//
const getTreeData = async () => {
const data = await getProductTree();
treeData.value = data;
};
getTreeData();
//
async function getProductTypeTreeFun() {
getProductTypeTree().then((res) => {
if (res.code == 0) {
productTypeTreeList.value = res.data
}
})
}
getProductTypeTreeFun()
//
const clickProductTypeTree = () => {
getClickProductFun()
params.product_guid = null
params.product_parts_guid = null
productList.length = 0
productPartsList.length = 0
}
//
const clickProduct = () => {
getClickProductPartsFun()
params.product_parts_guid = null
productPartsList.length = 0
}
//
async function getClickProductFun() {
getClickProduct({ product_type_guid: params.product_type }).then((res) => {
if (res.code == 0) {
productList.value = res.data
}
})
}
//
async function getClickProductPartsFun() {
getClickProductParts({ product_guid: params.product_guid }).then((res) => {
if (res.code == 0) {
productPartsList.value = res.data
}
})
}
function findDataOf(data, rules, res) {
top: for (let item of data) {
if (item.children.length !== 0) {
findDataOf(item.children, rules, res)
}
for (let key in rules) {
if (item.data.product_guid === rules[key]) {
res.push(data)
break top
}
}
}
}
//
const handleNodeClick = (value) => {
const { type, children, data } = value;
switch (type) {
//
case "product_type":
if (data.parent_id == '0') return
params.product_type = data.product_type_guid;
clickProductTypeTree()
// console.log(data,'dart');
// //
// changeDataPropertyName(children,{
// id:'product_guid',
// name:'product_name',
// },true)
// productList.value = children;
// params.product_guid = "";
// params.product_parts_guid = "";
break;
//
case "product":
let res_product = []
findDataOf(treeData.value, data, res_product)
console.log(res_product, 'asdasdasdas');
if (res_product.length == 2) {
//
changeDataPropertyName(res_product[1], {
id: 'product_guid',
name: 'product_name',
}, true)
changeDataPropertyName(res_product[0], {
id: 'product_parts_guid',
name: 'product_parts_name',
}, true)
productList.value = res_product[1];
productPartsList.value = res_product[0];
}
if (res_product.length == 1) {
//
changeDataPropertyName(res_product[0], {
id: 'product_guid',
name: 'product_name',
}, true)
productList.value = res_product[0];
}
params.product_type = data.product_type_guid;
params.product_guid = data.product_guid;
params.product_parts_guid = "";
break;
//
case "product_parts":
let res = []
// "298b6201-eb5b-bca8-c5a6-b77ba45f6ffe"
console.log(treeData.value, 'this is t');
console.log(data, 'this is data');
findDataOf(treeData.value, data, res)
let product = res[1]
let product_parts = res[0]
console.log(res, 'this is res');
changeDataPropertyName(product, {
id: 'product_guid',
name: 'product_name',
}, true)
changeDataPropertyName(product_parts, {
id: 'product_parts_guid',
name: 'product_parts_name',
}, true)
productList.value = product;
productPartsList.value = product_parts;
params.product_type = data.product_type_guid;
params.product_guid = data.product_guid;
params.product_parts_guid = data.product_parts_guid;
break;
default:
break;
}
};
const handleCommand = ({ type, row }) => {
switch (type) {
case "detail":
handleDetail(row);
break;
case 'delete':
handleDelete([row]);
break;
}
};
//
const handleDelete = data => {
ElMessageBox.confirm(`您确定要删除该学生吗?`).then(async () => {
const res = await deleteStudent({
student_guid: data.map(v => v.student_guid).join()
});
if (res) {
tableRef.value.reload();
}
});
};
//
function handleUpdate(row) {
EditStudentDialogVisible.value = true
EditStudentDialogRow.value = row
}
//
function handleDetail(row) {
DetailStudentDialogVisible.value = true
DetailStudentDialogRow.value = row
}
let loading = null;
const uploadLoading = () => {
loading = ElLoading.service({
lock: true,
text: "正在导入中...",
background: "rgba(255, 255, 255, 0.7)",
});
};
const closeUploadLoading = () => loading.close();
const handleExcelSuccess = (value) => {
if (value.code == 0) {
ElMessageBox.alert(value.msg, "导入信息", {
dangerouslyUseHTMLString: true,
confirmButtonText: "确定",
});
} else {
ElMessage.error(value.msg);
}
closeUploadLoading();
// ImportMsgDialogVisible.value = true
// ImportMsgDialogRow.value = value.msg
tableRef.value.reload();
};
const AuditData = reactive({
student_guid: null,
student_audit_status: null,
})
/** 审核按钮操作 */
function handleAudit(row) {
const Ids = row.student_guid || selectionData.value.map(v => v.student_guid).join()
console.log(Ids);
ElMessageBox.confirm("是否通过审核?", "系统提示", {
distinguishCancelAndClose: true,
confirmButtonText: '通过',
cancelButtonText: '驳回',
type: "warning",
})
.then(async () => {
AuditData.student_audit_status = 2
AuditData.student_guid = Ids
Audit()
})
.catch((action) => {
if (action == 'cancel') {
AuditData.student_audit_status = 3
AuditData.student_guid = Ids
Audit()
// console.log("");
}
else {
// console.log("");
}
})
}
//
async function Audit() {
auditStudent(AuditData).then((res) => {
if (res.code == 0) {
AuditData.student_audit_status = null
AuditData.student_guid = null
ElMessage.success(res.msg)
}
else{
ElMessage.error(res.msg)
}
tableRef.value.reload();
})
}
//
const sex = ref([]);
async function get_sex() {
await getDictionary({ dictionary_value: 'sex' }).then((res) => {
sex.value = res
})
}
get_sex()
//
const member_type = ref([]);
async function get_member_type() {
await getDictionary({ dictionary_value: 'member_type' }).then((res) => {
member_type.value = res
})
}
get_member_type()
//
const audit_status = ref([]);
async function get_audit_status() {
await getDictionary({ dictionary_value: 'audit_status' }).then((res) => {
audit_status.value = res
})
}
get_audit_status()
</script>

View File

@ -1,6 +1,31 @@
import { api, downloadFile, createApiUrl} from '~/utils/axios';
/**
* 导出班型
* @param {Object} data
* @return {Promise} api
*/
export function exportExcel(data) {
downloadFile(createApiUrl('Enrol.Classes/exportExcel'), data);
}
/**
* 下载班型模板
* @param {Object} data
* @return {Promise} api
*/
export function downloadTemplate(data) {
downloadFile(createApiUrl('Enrol.Classes/downloadTemplate'), data);
}
/**
* 导入班型
* @param {Object} data
* @return {Promise} api
*/
export const importExcel = createApiUrl('Enrol.Classes/importExcel');
@ -9,21 +34,21 @@ import { api, downloadFile, createApiUrl} from '~/utils/axios';
/**
* 获取班列表
* 获取班列表
* @param {Object} data
* @return {Promise} api
*/
export function getClassesList(data) {
return api.post('School.Classes/getClassesList', data);
return api.post('Enrol.Classes/getClassesList', data);
}
/**
* 删除班
* 删除班
* @param {Object} data
* @return {Promise} api
*/
export function deleteClasses(data) {
return api.post('School.Classes/deleteClasses', data, {
return api.post('Enrol.Classes/deleteClasses', data, {
isTransformResponse: true,
isShowSuccessMessage: true,
errorMessageText: '删除失败'
@ -31,24 +56,24 @@ export function deleteClasses(data) {
}
/**
* 添加班
* 添加班
* @param {Object} data
* @return {Promise} api
*/
export function addClasses(data) {
return api.post('School.Classes/addClasses', data, {
return api.post('Enrol.Classes/addClasses', data, {
isTransformResponse: true,
isShowSuccessMessage: true,
errorMessageText: '添加失败'
});
}
/**
* 编辑班
* 编辑班
* @param {Object} data
* @return {Promise} api
*/
export function editClasses(data) {
return api.post('School.Classes/editClasses', data, {
return api.post('Enrol.Classes/editClasses', data, {
isTransformResponse: true,
isShowSuccessMessage: true,
errorMessageText: '编辑失败'