dev-zcx
parent
95a198eab1
commit
99ed1be271
@ -0,0 +1,122 @@ |
|||||||
|
<template> |
||||||
|
<Dialog v-model="dialogVisible" :title="dialogTitle"> |
||||||
|
<el-form |
||||||
|
ref="formRef" |
||||||
|
v-loading="formLoading" |
||||||
|
:model="formData" |
||||||
|
:rules="formRules" |
||||||
|
label-width="80px" |
||||||
|
> |
||||||
|
<el-form-item label="字典名称" prop="name"> |
||||||
|
<el-input v-model="formData.name" placeholder="请输入字典名称" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="字典类型" prop="type"> |
||||||
|
<el-input |
||||||
|
v-model="formData.type" |
||||||
|
:disabled="typeof formData.id !== 'undefined'" |
||||||
|
placeholder="请输入参数名称" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="状态" prop="status"> |
||||||
|
<el-radio-group v-model="formData.status"> |
||||||
|
<el-radio |
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
||||||
|
:key="dict.value" |
||||||
|
:label="dict.value" |
||||||
|
> |
||||||
|
{{ dict.label }} |
||||||
|
</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="备注" prop="remark"> |
||||||
|
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<template #footer> |
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="SystemDictTypeForm" setup> |
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
||||||
|
import * as DictTypeApi from '@/api/system/dict/dict.type' |
||||||
|
import { CommonStatusEnum } from '@/utils/constants' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const dialogTitle = ref('') // 弹窗的标题 |
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
||||||
|
const formData = ref({ |
||||||
|
id: undefined, |
||||||
|
name: '', |
||||||
|
type: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
remark: '' |
||||||
|
}) |
||||||
|
const formRules = reactive({ |
||||||
|
name: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }], |
||||||
|
type: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }], |
||||||
|
status: [{ required: true, message: '状态不能为空', trigger: 'change' }] |
||||||
|
}) |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
|
||||||
|
/** 打开弹窗 */ |
||||||
|
const open = async (type: string, id?: number) => { |
||||||
|
dialogVisible.value = true |
||||||
|
dialogTitle.value = t('action.' + type) |
||||||
|
formType.value = type |
||||||
|
resetForm() |
||||||
|
// 修改时,设置数据 |
||||||
|
if (id) { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
formData.value = await DictTypeApi.getDictType(id) |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||||
|
const submitForm = async () => { |
||||||
|
// 校验表单 |
||||||
|
if (!formRef.value) return |
||||||
|
const valid = await formRef.value.validate() |
||||||
|
if (!valid) return |
||||||
|
// 提交请求 |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = formData.value as DictTypeApi.DictTypeVO |
||||||
|
if (formType.value === 'create') { |
||||||
|
await DictTypeApi.createDictType(data) |
||||||
|
message.success(t('common.createSuccess')) |
||||||
|
} else { |
||||||
|
await DictTypeApi.updateDictType(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
} |
||||||
|
dialogVisible.value = false |
||||||
|
// 发送操作成功的事件 |
||||||
|
emit('success') |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置表单 */ |
||||||
|
const resetForm = () => { |
||||||
|
formData.value = { |
||||||
|
id: undefined, |
||||||
|
type: '', |
||||||
|
name: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
remark: '' |
||||||
|
} |
||||||
|
formRef.value?.resetFields() |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,181 @@ |
|||||||
|
<template> |
||||||
|
<Dialog v-model="dialogVisible" :title="dialogTitle"> |
||||||
|
<el-form |
||||||
|
ref="formRef" |
||||||
|
v-loading="formLoading" |
||||||
|
:model="formData" |
||||||
|
:rules="formRules" |
||||||
|
label-width="80px" |
||||||
|
> |
||||||
|
<el-form-item label="字典类型" prop="type"> |
||||||
|
<el-input |
||||||
|
v-model="formData.dictType" |
||||||
|
:disabled="typeof formData.id !== 'undefined'" |
||||||
|
placeholder="请输入参数名称" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="数据标签" prop="label"> |
||||||
|
<el-input v-model="formData.label" placeholder="请输入数据标签" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="数据键值" prop="value"> |
||||||
|
<el-input v-model="formData.value" placeholder="请输入数据键值" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="显示排序" prop="sort"> |
||||||
|
<el-input-number v-model="formData.sort" :min="0" controls-position="right" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="状态" prop="status"> |
||||||
|
<el-radio-group v-model="formData.status"> |
||||||
|
<el-radio |
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
||||||
|
:key="dict.value" |
||||||
|
:label="dict.value" |
||||||
|
> |
||||||
|
{{ dict.label }} |
||||||
|
</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="颜色类型" prop="colorType"> |
||||||
|
<el-select v-model="formData.colorType"> |
||||||
|
<el-option |
||||||
|
v-for="item in colorTypeOptions" |
||||||
|
:key="item.value" |
||||||
|
:label="item.label + '(' + item.value + ')'" |
||||||
|
:value="item.value" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="CSS Class" prop="cssClass"> |
||||||
|
<el-input v-model="formData.cssClass" placeholder="请输入 CSS Class" /> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="备注" prop="remark"> |
||||||
|
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<template #footer> |
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="SystemDictDataForm" setup> |
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
||||||
|
import * as DictDataApi from '@/api/system/dict/dict.data' |
||||||
|
import { CommonStatusEnum } from '@/utils/constants' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const dialogTitle = ref('') // 弹窗的标题 |
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
||||||
|
const formData = ref({ |
||||||
|
id: undefined, |
||||||
|
sort: undefined, |
||||||
|
label: '', |
||||||
|
value: '', |
||||||
|
dictType: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
colorType: '', |
||||||
|
cssClass: '', |
||||||
|
remark: '' |
||||||
|
}) |
||||||
|
const formRules = reactive({ |
||||||
|
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], |
||||||
|
value: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }], |
||||||
|
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }], |
||||||
|
status: [{ required: true, message: '状态不能为空', trigger: 'change' }] |
||||||
|
}) |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
|
||||||
|
// 数据标签回显样式 |
||||||
|
const colorTypeOptions = readonly([ |
||||||
|
{ |
||||||
|
value: 'default', |
||||||
|
label: '默认' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 'primary', |
||||||
|
label: '主要' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 'success', |
||||||
|
label: '成功' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 'info', |
||||||
|
label: '信息' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 'warning', |
||||||
|
label: '警告' |
||||||
|
}, |
||||||
|
{ |
||||||
|
value: 'danger', |
||||||
|
label: '危险' |
||||||
|
} |
||||||
|
]) |
||||||
|
|
||||||
|
/** 打开弹窗 */ |
||||||
|
const open = async (type: string, id?: number, dictType?: string) => { |
||||||
|
dialogVisible.value = true |
||||||
|
dialogTitle.value = t('action.' + type) |
||||||
|
formType.value = type |
||||||
|
resetForm() |
||||||
|
if (dictType) { |
||||||
|
formData.value.dictType = dictType |
||||||
|
} |
||||||
|
// 修改时,设置数据 |
||||||
|
if (id) { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
formData.value = await DictDataApi.getDictData(id) |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||||
|
const submitForm = async () => { |
||||||
|
// 校验表单 |
||||||
|
if (!formRef.value) return |
||||||
|
const valid = await formRef.value.validate() |
||||||
|
if (!valid) return |
||||||
|
// 提交请求 |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = formData.value as DictDataApi.DictDataVO |
||||||
|
if (formType.value === 'create') { |
||||||
|
await DictDataApi.createDictData(data) |
||||||
|
message.success(t('common.createSuccess')) |
||||||
|
} else { |
||||||
|
await DictDataApi.updateDictData(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
} |
||||||
|
dialogVisible.value = false |
||||||
|
// 发送操作成功的事件 |
||||||
|
emit('success') |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置表单 */ |
||||||
|
const resetForm = () => { |
||||||
|
formData.value = { |
||||||
|
id: undefined, |
||||||
|
sort: undefined, |
||||||
|
label: '', |
||||||
|
value: '', |
||||||
|
dictType: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
colorType: '', |
||||||
|
cssClass: '', |
||||||
|
remark: '' |
||||||
|
} |
||||||
|
formRef.value?.resetFields() |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,207 @@ |
|||||||
|
<template> |
||||||
|
<ContentWrap> |
||||||
|
<el-form |
||||||
|
class="-mb-15px" |
||||||
|
:model="queryParams" |
||||||
|
ref="queryFormRef" |
||||||
|
:inline="true" |
||||||
|
label-width="68px" |
||||||
|
> |
||||||
|
<el-form-item label="字典名称" prop="dictType"> |
||||||
|
<el-select v-model="queryParams.dictType" class="!w-240px"> |
||||||
|
<el-option |
||||||
|
v-for="item in dictTypeList" |
||||||
|
:key="item.type" |
||||||
|
:label="item.name" |
||||||
|
:value="item.type" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="字典标签" prop="label"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.label" |
||||||
|
placeholder="请输入字典标签" |
||||||
|
clearable |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
class="!w-240px" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="状态" prop="status"> |
||||||
|
<el-select v-model="queryParams.status" placeholder="数据状态" clearable class="!w-240px"> |
||||||
|
<el-option |
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
||||||
|
:key="dict.value" |
||||||
|
:label="dict.label" |
||||||
|
:value="dict.value" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> |
||||||
|
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
plain |
||||||
|
@click="openForm('create')" |
||||||
|
v-hasPermi="['system:dict:create']" |
||||||
|
> |
||||||
|
<Icon icon="ep:plus" class="mr-5px" /> 新增 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
type="success" |
||||||
|
plain |
||||||
|
@click="handleExport" |
||||||
|
:loading="exportLoading" |
||||||
|
v-hasPermi="['system:dict:export']" |
||||||
|
> |
||||||
|
<Icon icon="ep:download" class="mr-5px" /> 导出 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</ContentWrap> |
||||||
|
|
||||||
|
<!-- 列表 --> |
||||||
|
<ContentWrap> |
||||||
|
<el-table v-loading="loading" :data="list"> |
||||||
|
<el-table-column label="字典编码" align="center" prop="id" /> |
||||||
|
<el-table-column label="字典标签" align="center" prop="label" /> |
||||||
|
<el-table-column label="字典键值" align="center" prop="value" /> |
||||||
|
<el-table-column label="字典排序" align="center" prop="sort" /> |
||||||
|
<el-table-column label="状态" align="center" prop="status"> |
||||||
|
<template #default="scope"> |
||||||
|
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="颜色类型" align="center" prop="colorType" /> |
||||||
|
<el-table-column label="CSS Class" align="center" prop="cssClass" /> |
||||||
|
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip /> |
||||||
|
<el-table-column |
||||||
|
label="创建时间" |
||||||
|
align="center" |
||||||
|
prop="createTime" |
||||||
|
width="180" |
||||||
|
:formatter="dateFormatter" |
||||||
|
/> |
||||||
|
<el-table-column label="操作" align="center"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-button |
||||||
|
link |
||||||
|
type="primary" |
||||||
|
@click="openForm('update', scope.row.id)" |
||||||
|
v-hasPermi="['system:dict:update']" |
||||||
|
> |
||||||
|
修改 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
link |
||||||
|
type="danger" |
||||||
|
@click="handleDelete(scope.row.id)" |
||||||
|
v-hasPermi="['system:dict:delete']" |
||||||
|
> |
||||||
|
删除 |
||||||
|
</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<!-- 分页 --> |
||||||
|
<Pagination |
||||||
|
:total="total" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</ContentWrap> |
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 --> |
||||||
|
<DictDataForm ref="formRef" @success="getList" /> |
||||||
|
</template> |
||||||
|
<script setup lang="ts" name="SystemDictData"> |
||||||
|
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' |
||||||
|
import { dateFormatter } from '@/utils/formatTime' |
||||||
|
import download from '@/utils/download' |
||||||
|
import * as DictDataApi from '@/api/system/dict/dict.data' |
||||||
|
import * as DictTypeApi from '@/api/system/dict/dict.type' |
||||||
|
import DictDataForm from './DictDataForm.vue' |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const route = useRoute() // 路由 |
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中 |
||||||
|
const total = ref(0) // 列表的总页数 |
||||||
|
const list = ref([]) // 列表的数据 |
||||||
|
const queryParams = reactive({ |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
label: '', |
||||||
|
status: undefined, |
||||||
|
dictType: route.params.dictType |
||||||
|
}) |
||||||
|
const queryFormRef = ref() // 搜索的表单 |
||||||
|
const exportLoading = ref(false) // 导出的加载中 |
||||||
|
const dictTypeList = ref<DictTypeApi.DictTypeVO[]>() // 字典类型的列表 |
||||||
|
|
||||||
|
/** 查询列表 */ |
||||||
|
const getList = async () => { |
||||||
|
loading.value = true |
||||||
|
try { |
||||||
|
const data = await DictDataApi.getDictDataPage(queryParams) |
||||||
|
list.value = data.list |
||||||
|
total.value = data.total |
||||||
|
} finally { |
||||||
|
loading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 搜索按钮操作 */ |
||||||
|
const handleQuery = () => { |
||||||
|
queryParams.pageNo = 1 |
||||||
|
getList() |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置按钮操作 */ |
||||||
|
const resetQuery = () => { |
||||||
|
queryFormRef.value.resetFields() |
||||||
|
handleQuery() |
||||||
|
} |
||||||
|
|
||||||
|
/** 添加/修改操作 */ |
||||||
|
const formRef = ref() |
||||||
|
const openForm = (type: string, id?: number) => { |
||||||
|
formRef.value.open(type, id, queryParams.dictType) |
||||||
|
} |
||||||
|
|
||||||
|
/** 删除按钮操作 */ |
||||||
|
const handleDelete = async (id: number) => { |
||||||
|
try { |
||||||
|
// 删除的二次确认 |
||||||
|
await message.delConfirm() |
||||||
|
// 发起删除 |
||||||
|
await DictDataApi.deleteDictData(id) |
||||||
|
message.success(t('common.delSuccess')) |
||||||
|
// 刷新列表 |
||||||
|
await getList() |
||||||
|
} catch {} |
||||||
|
} |
||||||
|
|
||||||
|
/** 导出按钮操作 */ |
||||||
|
const handleExport = async () => { |
||||||
|
try { |
||||||
|
// 导出的二次确认 |
||||||
|
await message.exportConfirm() |
||||||
|
// 发起导出 |
||||||
|
exportLoading.value = true |
||||||
|
const data = await DictDataApi.exportDictData(queryParams) |
||||||
|
download.excel(data, '字典数据.xls') |
||||||
|
} catch { |
||||||
|
} finally { |
||||||
|
exportLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 初始化 **/ |
||||||
|
onMounted(async () => { |
||||||
|
await getList() |
||||||
|
// 查询字典(精简)列表 |
||||||
|
dictTypeList.value = await DictTypeApi.getSimpleDictTypeList() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,229 @@ |
|||||||
|
<template> |
||||||
|
<!-- 搜索工作栏 --> |
||||||
|
<ContentWrap> |
||||||
|
<el-form |
||||||
|
ref="queryFormRef" |
||||||
|
:inline="true" |
||||||
|
:model="queryParams" |
||||||
|
class="-mb-15px" |
||||||
|
label-width="68px" |
||||||
|
> |
||||||
|
<el-form-item label="字典名称" prop="name"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.name" |
||||||
|
class="!w-240px" |
||||||
|
clearable |
||||||
|
placeholder="请输入字典名称" |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="字典类型" prop="type"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.type" |
||||||
|
class="!w-240px" |
||||||
|
clearable |
||||||
|
placeholder="请输入字典类型" |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="状态" prop="status"> |
||||||
|
<el-select |
||||||
|
v-model="queryParams.status" |
||||||
|
class="!w-240px" |
||||||
|
clearable |
||||||
|
placeholder="请选择字典状态" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
||||||
|
:key="dict.value" |
||||||
|
:label="dict.label" |
||||||
|
:value="dict.value" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="创建时间" prop="createTime"> |
||||||
|
<el-date-picker |
||||||
|
v-model="queryParams.createTime" |
||||||
|
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" |
||||||
|
class="!w-240px" |
||||||
|
end-placeholder="结束日期" |
||||||
|
start-placeholder="开始日期" |
||||||
|
type="daterange" |
||||||
|
value-format="yyyy-MM-dd HH:mm:ss" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button @click="handleQuery"> |
||||||
|
<Icon class="mr-5px" icon="ep:search" /> |
||||||
|
搜索 |
||||||
|
</el-button> |
||||||
|
<el-button @click="resetQuery"> |
||||||
|
<Icon class="mr-5px" icon="ep:refresh" /> |
||||||
|
重置 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
v-hasPermi="['system:dict:create']" |
||||||
|
plain |
||||||
|
type="primary" |
||||||
|
@click="openForm('create')" |
||||||
|
> |
||||||
|
<Icon class="mr-5px" icon="ep:plus" /> |
||||||
|
新增 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
v-hasPermi="['system:dict:export']" |
||||||
|
:loading="exportLoading" |
||||||
|
plain |
||||||
|
type="success" |
||||||
|
@click="handleExport" |
||||||
|
> |
||||||
|
<Icon class="mr-5px" icon="ep:download" /> |
||||||
|
导出 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</ContentWrap> |
||||||
|
|
||||||
|
<!-- 列表 --> |
||||||
|
<ContentWrap> |
||||||
|
<el-table v-loading="loading" :data="list"> |
||||||
|
<el-table-column align="center" label="字典编号" prop="id" /> |
||||||
|
<el-table-column align="center" label="字典名称" prop="name" show-overflow-tooltip /> |
||||||
|
<el-table-column align="center" label="字典类型" prop="type" width="300" /> |
||||||
|
<el-table-column align="center" label="状态" prop="status"> |
||||||
|
<template #default="scope"> |
||||||
|
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column align="center" label="备注" prop="remark" /> |
||||||
|
<el-table-column |
||||||
|
:formatter="dateFormatter" |
||||||
|
align="center" |
||||||
|
label="创建时间" |
||||||
|
prop="createTime" |
||||||
|
width="180" |
||||||
|
/> |
||||||
|
<el-table-column align="center" label="操作"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-button |
||||||
|
v-hasPermi="['system:dict:update']" |
||||||
|
link |
||||||
|
type="primary" |
||||||
|
@click="openForm('update', scope.row.id)" |
||||||
|
> |
||||||
|
修改 |
||||||
|
</el-button> |
||||||
|
<router-link :to="'/dict/type/data/' + scope.row.type"> |
||||||
|
<el-button link type="primary">数据</el-button> |
||||||
|
</router-link> |
||||||
|
<el-button |
||||||
|
v-hasPermi="['system:dict:delete']" |
||||||
|
link |
||||||
|
type="danger" |
||||||
|
@click="handleDelete(scope.row.id)" |
||||||
|
> |
||||||
|
删除 |
||||||
|
</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<!-- 分页 --> |
||||||
|
<Pagination |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
:total="total" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</ContentWrap> |
||||||
|
|
||||||
|
<!-- 表单弹窗:添加/修改 --> |
||||||
|
<DictTypeForm ref="formRef" @success="getList" /> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" name="SystemDictType" setup> |
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
||||||
|
import { dateFormatter } from '@/utils/formatTime' |
||||||
|
import * as DictTypeApi from '@/api/system/dict/dict.type' |
||||||
|
import DictTypeForm from './DictTypeForm.vue' |
||||||
|
import download from '@/utils/download' |
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中 |
||||||
|
const total = ref(0) // 列表的总页数 |
||||||
|
const list = ref([]) // 字典表格数据 |
||||||
|
const queryParams = reactive({ |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
name: '', |
||||||
|
type: '', |
||||||
|
status: undefined, |
||||||
|
createTime: [] |
||||||
|
}) |
||||||
|
const queryFormRef = ref() // 搜索的表单 |
||||||
|
const exportLoading = ref(false) // 导出的加载中 |
||||||
|
|
||||||
|
/** 查询字典类型列表 */ |
||||||
|
const getList = async () => { |
||||||
|
loading.value = true |
||||||
|
try { |
||||||
|
const data = await DictTypeApi.getDictTypePage(queryParams) |
||||||
|
list.value = data.list |
||||||
|
total.value = data.total |
||||||
|
} finally { |
||||||
|
loading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 搜索按钮操作 */ |
||||||
|
const handleQuery = () => { |
||||||
|
queryParams.pageNo = 1 |
||||||
|
getList() |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置按钮操作 */ |
||||||
|
const resetQuery = () => { |
||||||
|
queryFormRef.value.resetFields() |
||||||
|
handleQuery() |
||||||
|
} |
||||||
|
|
||||||
|
/** 添加/修改操作 */ |
||||||
|
const formRef = ref() |
||||||
|
const openForm = (type: string, id?: number) => { |
||||||
|
formRef.value.open(type, id) |
||||||
|
} |
||||||
|
|
||||||
|
/** 删除按钮操作 */ |
||||||
|
const handleDelete = async (id: number) => { |
||||||
|
try { |
||||||
|
// 删除的二次确认 |
||||||
|
await message.delConfirm() |
||||||
|
// 发起删除 |
||||||
|
await DictTypeApi.deleteDictType(id) |
||||||
|
message.success(t('common.delSuccess')) |
||||||
|
// 刷新列表 |
||||||
|
await getList() |
||||||
|
} catch {} |
||||||
|
} |
||||||
|
|
||||||
|
/** 导出按钮操作 */ |
||||||
|
const handleExport = async () => { |
||||||
|
try { |
||||||
|
// 导出的二次确认 |
||||||
|
await message.exportConfirm() |
||||||
|
// 发起导出 |
||||||
|
exportLoading.value = true |
||||||
|
const data = await DictTypeApi.exportDictType(queryParams) |
||||||
|
download.excel(data, '字典类型.xls') |
||||||
|
} catch { |
||||||
|
} finally { |
||||||
|
exportLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 初始化 **/ |
||||||
|
onMounted(() => { |
||||||
|
getList() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,83 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-table v-loading="loading" :data="tableList" border> |
||||||
|
<el-table-column type="index" width="50" /> |
||||||
|
<el-table-column |
||||||
|
v-for="col in columns" |
||||||
|
:prop="col.prop" |
||||||
|
:key="col.prop" |
||||||
|
:label="col.label" |
||||||
|
:width="col.width" |
||||||
|
/> |
||||||
|
<el-table-column label="状态" key="status"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.status" |
||||||
|
:active-value="0" |
||||||
|
active-text="在职" |
||||||
|
inactive-text="离职" |
||||||
|
:inactive-value="1" |
||||||
|
disabled |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<Pagination |
||||||
|
v-model:limit="pageSize" |
||||||
|
v-model:page="currentPage" |
||||||
|
:total="total" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="RoleEmployee"> |
||||||
|
import { getRoleUsers } from '@/api/system/role' |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
roleId: { |
||||||
|
type: Number |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
watch( |
||||||
|
() => props.roleId, |
||||||
|
(newValue) => { |
||||||
|
getList(newValue) |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
const loading = ref(false) |
||||||
|
const tableList = ref([]) |
||||||
|
const total = ref(0) |
||||||
|
const pageSize = ref(20) |
||||||
|
const currentPage = ref(1) |
||||||
|
|
||||||
|
const columns = ref([ |
||||||
|
{ prop: 'name', label: '姓名', width: '200px' }, |
||||||
|
{ prop: 'mobile', label: '手机号', width: '150px' }, |
||||||
|
{ prop: 'deptName', label: '部门' }, |
||||||
|
{ prop: 'roles', label: '角色' } |
||||||
|
]) |
||||||
|
|
||||||
|
async function getList() { |
||||||
|
loading.value = true |
||||||
|
try { |
||||||
|
const data = await getRoleUsers({ |
||||||
|
pageNo: currentPage.value, |
||||||
|
pageSize: pageSize.value, |
||||||
|
id: props.roleId |
||||||
|
}) |
||||||
|
tableList.value = data.list |
||||||
|
total.value = data.total |
||||||
|
} finally { |
||||||
|
loading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
getList() |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,99 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-form ref="formRef" v-loading="formLoading" label-width="0px"> |
||||||
|
<el-form-item> |
||||||
|
<el-tree |
||||||
|
ref="treeRef" |
||||||
|
:data="menuOptions" |
||||||
|
:props="defaultProps" |
||||||
|
empty-text="加载中,请稍候" |
||||||
|
node-key="id" |
||||||
|
show-checkbox |
||||||
|
style="width: 100%" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button |
||||||
|
:disabled="formLoading" |
||||||
|
type="primary" |
||||||
|
@click="submitForm" |
||||||
|
v-hasPermi="['basic:role:update-menu']" |
||||||
|
>保存权限</el-button |
||||||
|
> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="RoleAssignMenuForm" setup> |
||||||
|
import { defaultProps, handleTree } from '@/utils/tree' |
||||||
|
import * as MenuApi from '@/api/system/menu' |
||||||
|
import * as PermissionApi from '@/api/system/permission' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
roleId: { |
||||||
|
type: Number |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
watch( |
||||||
|
() => props.roleId, |
||||||
|
(newValue) => { |
||||||
|
getCheckedMenu(newValue) |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
const menuOptions = ref<any[]>([]) // 菜单树形结构 |
||||||
|
const treeRef = ref() // 菜单树组件 Ref |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const submitForm = async () => { |
||||||
|
// 提交请求 |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = { |
||||||
|
roleId: props.roleId, |
||||||
|
menuIds: [ |
||||||
|
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点 |
||||||
|
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点 |
||||||
|
] |
||||||
|
} |
||||||
|
await PermissionApi.assignRoleMenu(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
dialogVisible.value = false |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const checkedMenuIds = ref([]) |
||||||
|
|
||||||
|
async function init() { |
||||||
|
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList()) |
||||||
|
getCheckedMenu(props.roleId) |
||||||
|
} |
||||||
|
|
||||||
|
async function getCheckedMenu(id) { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
checkedMenuIds.value = await PermissionApi.getRoleMenuList(id) |
||||||
|
treeRef.value.setCheckedKeys([], false) |
||||||
|
// 设置选中 |
||||||
|
checkedMenuIds.value.forEach((menuId: number) => { |
||||||
|
treeRef.value.setChecked(menuId, true, false) |
||||||
|
}) |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
init() |
||||||
|
}) |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,166 @@ |
|||||||
|
<template> |
||||||
|
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px"> |
||||||
|
<el-form-item label="权限范围"> |
||||||
|
<el-select v-model="formData.dataScope"> |
||||||
|
<el-option |
||||||
|
v-for="item in dataScopeOptions" |
||||||
|
:key="item.value" |
||||||
|
:label="item.label" |
||||||
|
:value="item.value" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item |
||||||
|
v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM" |
||||||
|
label="权限范围" |
||||||
|
style="display: flex" |
||||||
|
> |
||||||
|
<el-card class="card" shadow="never"> |
||||||
|
<template #header> |
||||||
|
全选/全不选: |
||||||
|
<el-switch |
||||||
|
v-model="treeNodeAll" |
||||||
|
active-text="是" |
||||||
|
inactive-text="否" |
||||||
|
inline-prompt |
||||||
|
@change="handleCheckedTreeNodeAll()" |
||||||
|
/> |
||||||
|
全部展开/折叠: |
||||||
|
<el-switch |
||||||
|
v-model="deptExpand" |
||||||
|
active-text="展开" |
||||||
|
inactive-text="折叠" |
||||||
|
inline-prompt |
||||||
|
@change="handleCheckedTreeExpand" |
||||||
|
/> |
||||||
|
父子联动(选中父节点,自动选择子节点): |
||||||
|
<el-switch v-model="checkStrictly" active-text="是" inactive-text="否" inline-prompt /> |
||||||
|
</template> |
||||||
|
<el-tree |
||||||
|
ref="treeRef" |
||||||
|
:check-strictly="!checkStrictly" |
||||||
|
:data="deptOptions" |
||||||
|
:props="defaultProps" |
||||||
|
default-expand-all |
||||||
|
empty-text="加载中,请稍后" |
||||||
|
node-key="id" |
||||||
|
show-checkbox |
||||||
|
/> |
||||||
|
</el-card> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label-width="0"> |
||||||
|
<el-button |
||||||
|
:disabled="formLoading" |
||||||
|
type="primary" |
||||||
|
@click="submitForm" |
||||||
|
v-hasPermi="['basic:role:update-data']" |
||||||
|
>保存权限</el-button |
||||||
|
> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="RoleDataPermissionForm" setup> |
||||||
|
import { defaultProps, handleTree } from '@/utils/tree' |
||||||
|
import { SystemDataScopeEnum } from '@/utils/constants' |
||||||
|
|
||||||
|
import * as DeptApi from '@/api/system/dept' |
||||||
|
import * as PermissionApi from '@/api/system/permission' |
||||||
|
import * as RoleApi from '@/api/system/role' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
roleId: { |
||||||
|
type: Number |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
watch( |
||||||
|
() => props.roleId, |
||||||
|
(newValue) => { |
||||||
|
getRoleInfo(newValue) |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formData = ref({ |
||||||
|
id: 0, |
||||||
|
name: '', |
||||||
|
dataScope: undefined, |
||||||
|
dataScopeDeptIds: [] |
||||||
|
}) |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
const deptOptions = ref<any[]>([]) // 部门树形结构 |
||||||
|
const deptExpand = ref(false) // 展开/折叠 |
||||||
|
const treeRef = ref() // 菜单树组件 Ref |
||||||
|
const treeNodeAll = ref(false) // 全选/全不选 |
||||||
|
const checkStrictly = ref(true) // 是否严格模式,即父子不关联 |
||||||
|
|
||||||
|
// const dataScopeOptions = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE) |
||||||
|
const dataScopeOptions = [ |
||||||
|
{ label: '全部数据权限', value: 1 }, |
||||||
|
{ label: '指定部门数据权限', value: 2 }, |
||||||
|
{ label: '部门数据权限', value: 3 }, |
||||||
|
{ label: '部门及以下数据权限', value: 4 }, |
||||||
|
{ label: '仅本人数据权限', value: 5 } |
||||||
|
] |
||||||
|
|
||||||
|
async function getRoleInfo(id) { |
||||||
|
try { |
||||||
|
formData.value = await RoleApi.getRole(id) |
||||||
|
nextTick(() => { |
||||||
|
treeRef.value.setCheckedKeys(formData.value.dataScopeDeptIds) |
||||||
|
}) |
||||||
|
} catch (error) { |
||||||
|
console.log(error) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||||
|
const submitForm = async () => { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = { |
||||||
|
roleId: formData.value.id, |
||||||
|
dataScope: formData.value.dataScope, |
||||||
|
dataScopeDeptIds: |
||||||
|
formData.value.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM |
||||||
|
? [] |
||||||
|
: treeRef.value.getCheckedKeys(false) |
||||||
|
} |
||||||
|
await PermissionApi.assignRoleDataScope(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
// 发送操作成功的事件 |
||||||
|
emit('success') |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 全选/全不选 */ |
||||||
|
const handleCheckedTreeNodeAll = () => { |
||||||
|
treeRef.value.setCheckedNodes(treeNodeAll.value ? deptOptions.value : []) |
||||||
|
} |
||||||
|
|
||||||
|
/** 展开/折叠全部 */ |
||||||
|
const handleCheckedTreeExpand = () => { |
||||||
|
const nodes = treeRef.value?.store.nodesMap |
||||||
|
for (let node in nodes) { |
||||||
|
if (nodes[node].expanded === deptExpand.value) { |
||||||
|
continue |
||||||
|
} |
||||||
|
nodes[node].expanded = deptExpand.value |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
async function init() { |
||||||
|
getRoleInfo(props.roleId) |
||||||
|
deptOptions.value = handleTree(await DeptApi.getSimpleDeptList()) |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
init() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,96 @@ |
|||||||
|
<template> |
||||||
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="400px"> |
||||||
|
<el-form |
||||||
|
ref="formRef" |
||||||
|
v-loading="formLoading" |
||||||
|
:model="formData" |
||||||
|
:rules="formRules" |
||||||
|
label-width="80px" |
||||||
|
> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="24" :offset="0"> |
||||||
|
<el-form-item label="角色名称" prop="name"> |
||||||
|
<el-input v-model="formData.name" placeholder="请输入角色名称" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<template #footer> |
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="SystemRoleForm" setup> |
||||||
|
// import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
||||||
|
import * as RoleApi from '@/api/system/role' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const dialogTitle = ref('') // 弹窗的标题 |
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
||||||
|
const formData = ref({ |
||||||
|
id: undefined, |
||||||
|
name: '' |
||||||
|
}) |
||||||
|
const formRules = reactive({ |
||||||
|
name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }] |
||||||
|
}) |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
|
||||||
|
/** 打开弹窗 */ |
||||||
|
const open = async (type: string, id?: number) => { |
||||||
|
dialogVisible.value = true |
||||||
|
dialogTitle.value = t('action.' + type) |
||||||
|
formType.value = type |
||||||
|
resetForm() |
||||||
|
// 修改时,设置数据 |
||||||
|
if (id) { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
formData.value = await RoleApi.getRole(id) |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置表单 */ |
||||||
|
const resetForm = () => { |
||||||
|
formData.value = { |
||||||
|
id: undefined, |
||||||
|
name: '' |
||||||
|
} |
||||||
|
formRef.value?.resetFields() |
||||||
|
} |
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||||
|
const submitForm = async () => { |
||||||
|
// 校验表单 |
||||||
|
if (!formRef.value) return |
||||||
|
const valid = await formRef.value.validate() |
||||||
|
if (!valid) return |
||||||
|
// 提交请求 |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = formData.value as unknown as RoleApi.RoleVO |
||||||
|
if (formType.value === 'create') { |
||||||
|
await RoleApi.createRole(data) |
||||||
|
message.success(t('common.createSuccess')) |
||||||
|
} else { |
||||||
|
await RoleApi.updateRole(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
} |
||||||
|
dialogVisible.value = false |
||||||
|
// 发送操作成功的事件 |
||||||
|
emit('success') |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,147 @@ |
|||||||
|
<template> |
||||||
|
<div class="flex"> |
||||||
|
<el-card shadow="always" :body-style="{ padding: '10px' }"> |
||||||
|
<div class="flex justify-between items-center" style="width: 300px"> |
||||||
|
<div class="text-16px font-bold">角色列表</div> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
style="padding: 0px" |
||||||
|
text |
||||||
|
@click="openForm('create')" |
||||||
|
v-hasPermi="['basic:role:add']" |
||||||
|
> |
||||||
|
新增 |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
<div class="border-top-1px mt-10px pt-10px"> |
||||||
|
<div |
||||||
|
class="flex justify-between items-center pl-10px pr-10px cursor-pointer pt-5px pb-5px" |
||||||
|
v-for="(item, index) in list" |
||||||
|
:key="index" |
||||||
|
:class="{ actived: libraryIndex == index }" |
||||||
|
@click="libraryIndex = index" |
||||||
|
> |
||||||
|
<div class="flex-1 text-14px">{{ item.name }}</div> |
||||||
|
<div class="ml-10px"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
style="padding: 0px" |
||||||
|
text |
||||||
|
v-hasPermi="['basic:role:update']" |
||||||
|
@click="openForm('update', item.id)" |
||||||
|
> |
||||||
|
修改 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
class="ml-10px" |
||||||
|
style="padding: 0px" |
||||||
|
text |
||||||
|
v-hasPermi="['basic:role:delete']" |
||||||
|
@click="handleDelete(item.id)" |
||||||
|
> |
||||||
|
删除 |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<Pagination |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
layout="total, prev, pager, next" |
||||||
|
small |
||||||
|
:total="total" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</el-card> |
||||||
|
<el-card class="ml-20px" style="flex: 1" shadow="always" :body-style="{ padding: '10px' }"> |
||||||
|
<el-tabs v-if="list && list.length" v-model="roleOperateIndex" type="card"> |
||||||
|
<el-tab-pane label="角色用户" :name="1"> |
||||||
|
<RoleEmployee v-if="roleOperateIndex == 1" :roleId="list[libraryIndex].id" /> |
||||||
|
</el-tab-pane> |
||||||
|
<el-tab-pane label="菜单权限" :name="2"> |
||||||
|
<RoleAssignMenuForm |
||||||
|
v-if="roleOperateIndex == 2" |
||||||
|
ref="assignMenuFormRef" |
||||||
|
:roleId="list[libraryIndex].id" |
||||||
|
@success="getList" |
||||||
|
/> |
||||||
|
</el-tab-pane> |
||||||
|
<el-tab-pane label="数据权限" :name="3"> |
||||||
|
<RoleDataPermissionForm |
||||||
|
v-if="roleOperateIndex == 3" |
||||||
|
ref="dataPermissionFormRef" |
||||||
|
:roleId="list[libraryIndex].id" |
||||||
|
@success="getList" |
||||||
|
/> |
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
</el-card> |
||||||
|
<!-- 表单弹窗:添加/修改 --> |
||||||
|
<RoleForm ref="formRef" @success="getList" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="SystemRole" setup> |
||||||
|
import RoleForm from './RoleForm.vue' |
||||||
|
import RoleEmployee from './Comp/RoleEmployee.vue' |
||||||
|
import RoleAssignMenuForm from './RoleAssignMenuForm.vue' |
||||||
|
import RoleDataPermissionForm from './RoleDataPermissionForm.vue' |
||||||
|
import * as RoleApi from '@/api/system/role' |
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
|
||||||
|
const total = ref(0) // 列表的总页数 |
||||||
|
const list = ref<any>([]) // 列表的数据 |
||||||
|
|
||||||
|
const libraryIndex = ref(0) |
||||||
|
const queryParams = reactive({ |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 20 |
||||||
|
}) |
||||||
|
|
||||||
|
/** 查询角色列表 */ |
||||||
|
const getList = async () => { |
||||||
|
const data = await RoleApi.getRolePage(queryParams) |
||||||
|
list.value = data.list |
||||||
|
total.value = data.total |
||||||
|
} |
||||||
|
|
||||||
|
/** 添加/修改操作 */ |
||||||
|
const formRef = ref() |
||||||
|
const openForm = (type: string, id?: number) => { |
||||||
|
formRef.value.open(type, id) |
||||||
|
} |
||||||
|
|
||||||
|
/** 数据权限操作 */ |
||||||
|
const dataPermissionFormRef = ref() |
||||||
|
|
||||||
|
/** 菜单权限操作 */ |
||||||
|
const assignMenuFormRef = ref() |
||||||
|
|
||||||
|
/** 删除按钮操作 */ |
||||||
|
const handleDelete = async (id: number) => { |
||||||
|
try { |
||||||
|
// 删除的二次确认 |
||||||
|
await message.delConfirm() |
||||||
|
// 发起删除 |
||||||
|
await RoleApi.deleteRole(id) |
||||||
|
message.success(t('common.delSuccess')) |
||||||
|
// 刷新列表 |
||||||
|
await getList() |
||||||
|
} catch {} |
||||||
|
} |
||||||
|
|
||||||
|
const roleOperateIndex = ref(1) |
||||||
|
|
||||||
|
/** 初始化 **/ |
||||||
|
onMounted(() => { |
||||||
|
getList() |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.actived { |
||||||
|
background-color: var(--el-color-primary-light-9); |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,56 @@ |
|||||||
|
<template> |
||||||
|
<div class="head-container"> |
||||||
|
<el-input v-model="deptName" class="mb-20px" clearable placeholder="请输入部门名称"> |
||||||
|
<template #prefix> |
||||||
|
<Icon icon="ep:search" /> |
||||||
|
</template> |
||||||
|
</el-input> |
||||||
|
</div> |
||||||
|
<div class="head-container"> |
||||||
|
<el-tree |
||||||
|
ref="treeRef" |
||||||
|
:data="deptList" |
||||||
|
:expand-on-click-node="false" |
||||||
|
:filter-node-method="filterNode" |
||||||
|
:props="defaultProps" |
||||||
|
default-expand-all |
||||||
|
highlight-current |
||||||
|
node-key="id" |
||||||
|
@node-click="handleNodeClick" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" name="SystemUserDeptTree" setup> |
||||||
|
import { ElTree } from 'element-plus' |
||||||
|
import * as DeptApi from '@/api/system/dept' |
||||||
|
import { defaultProps, handleTree } from '@/utils/tree' |
||||||
|
|
||||||
|
const deptName = ref('') |
||||||
|
const deptList = ref<Tree[]>([]) // 树形结构 |
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>() |
||||||
|
|
||||||
|
/** 获得部门树 */ |
||||||
|
const getTree = async () => { |
||||||
|
const res = await DeptApi.getSimpleDeptList() |
||||||
|
deptList.value = [] |
||||||
|
deptList.value.push(...handleTree(res)) |
||||||
|
} |
||||||
|
|
||||||
|
/** 基于名字过滤 */ |
||||||
|
const filterNode = (name: string, data: Tree) => { |
||||||
|
if (!name) return true |
||||||
|
return data.name.includes(name) |
||||||
|
} |
||||||
|
|
||||||
|
/** 处理部门被点击 */ |
||||||
|
const handleNodeClick = async (row: { [key: string]: any }) => { |
||||||
|
emits('node-click', row) |
||||||
|
} |
||||||
|
const emits = defineEmits(['node-click']) |
||||||
|
|
||||||
|
/** 初始化 */ |
||||||
|
onMounted(async () => { |
||||||
|
await getTree() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,228 @@ |
|||||||
|
<template> |
||||||
|
<Dialog v-model="dialogVisible" :title="dialogTitle" style="width: 800px"> |
||||||
|
<el-form |
||||||
|
ref="formRef" |
||||||
|
v-loading="formLoading" |
||||||
|
:model="formData" |
||||||
|
:rules="formRules" |
||||||
|
label-width="80px" |
||||||
|
> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="用户姓名" prop="nickname"> |
||||||
|
<el-input v-model="formData.nickname" placeholder="请输入用户姓名" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<!-- <el-col :span="12"> |
||||||
|
<el-form-item label="用户性别"> |
||||||
|
<el-radio-group v-model="formData.sex"> |
||||||
|
<el-radio :value="1"> 男 </el-radio> |
||||||
|
<el-radio :value="2"> 女 </el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="归属部门" prop="deptId"> |
||||||
|
<el-tree-select |
||||||
|
v-model="formData.deptId" |
||||||
|
:data="deptList" |
||||||
|
:props="defaultProps" |
||||||
|
check-strictly |
||||||
|
node-key="id" |
||||||
|
placeholder="请选择归属部门" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> --> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="角色" prop="role"> |
||||||
|
<el-select |
||||||
|
v-model="formData.roleIds" |
||||||
|
multiple |
||||||
|
collapse-tags |
||||||
|
collapse-tags-tooltip |
||||||
|
:max-collapse-tags="2" |
||||||
|
placeholder="请选择角色" |
||||||
|
> |
||||||
|
<el-option |
||||||
|
v-for="item in roleOptions" |
||||||
|
:key="item.id" |
||||||
|
:label="item.name" |
||||||
|
:value="item.id" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="手机号码" prop="mobile"> |
||||||
|
<el-input v-model="formData.mobile" maxlength="11" placeholder="请输入手机号码" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="邮箱" prop="email"> |
||||||
|
<el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item v-if="formData.id === undefined" label="登录账号" prop="username"> |
||||||
|
<el-input v-model="formData.username" placeholder="请输入登录账号" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item v-if="formData.id === undefined" label="用户密码" prop="password"> |
||||||
|
<el-input |
||||||
|
v-model="formData.password" |
||||||
|
placeholder="请输入用户密码" |
||||||
|
show-password |
||||||
|
type="password" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<!-- <el-row :gutter="20"> |
||||||
|
<el-col :span="12" :offset="0"> |
||||||
|
<el-form-item label="入职日期" prop="hireDate"> |
||||||
|
<el-date-picker |
||||||
|
v-model="formData.hireDate" |
||||||
|
type="date" |
||||||
|
format="YYYY-MM-DD" |
||||||
|
value-format="YYYY-MM-DD" |
||||||
|
placeholder="选择日期时间" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> --> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="备注"> |
||||||
|
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<template #footer> |
||||||
|
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button> |
||||||
|
</template> |
||||||
|
</Dialog> |
||||||
|
</template> |
||||||
|
<script lang="ts" name="SystemUserForm" setup> |
||||||
|
import { CommonStatusEnum } from '@/utils/constants' |
||||||
|
// import { defaultProps, handleTree } from '@/utils/tree' |
||||||
|
import { handleTree } from '@/utils/tree' |
||||||
|
import { formatDate } from '@/utils/formatTime' |
||||||
|
|
||||||
|
import * as RoleApi from '@/api/system/role' |
||||||
|
import * as DeptApi from '@/api/system/dept' |
||||||
|
import * as UserApi from '@/api/system/user' |
||||||
|
|
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const dialogVisible = ref(false) // 弹窗的是否展示 |
||||||
|
const dialogTitle = ref('') // 弹窗的标题 |
||||||
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
||||||
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
||||||
|
const formData = ref({ |
||||||
|
nickname: '', |
||||||
|
deptId: '', |
||||||
|
mobile: '', |
||||||
|
email: '', |
||||||
|
id: undefined, |
||||||
|
username: '', |
||||||
|
password: '', |
||||||
|
sex: 1, |
||||||
|
remark: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
roleIds: [], |
||||||
|
hireDate: '' |
||||||
|
}) |
||||||
|
const formRules = ref<any>({ |
||||||
|
username: [{ required: true, message: '登录账号不能为空', trigger: 'blur' }], |
||||||
|
nickname: [{ required: true, message: '用户姓名不能为空', trigger: 'blur' }], |
||||||
|
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }], |
||||||
|
email: [ |
||||||
|
{ |
||||||
|
type: 'email', |
||||||
|
message: '请输入正确的邮箱地址', |
||||||
|
trigger: ['blur', 'change'] |
||||||
|
} |
||||||
|
], |
||||||
|
mobile: [{ required: true, message: '手机号不能为空', trigger: 'blur' }] |
||||||
|
}) |
||||||
|
const formRef = ref() // 表单 Ref |
||||||
|
const deptList = ref<Tree[]>([]) // 树形结构 |
||||||
|
const roleOptions = ref<any>([]) |
||||||
|
|
||||||
|
/** 打开弹窗 */ |
||||||
|
const open = async (type: string, id?: number) => { |
||||||
|
dialogVisible.value = true |
||||||
|
dialogTitle.value = t('action.' + type) |
||||||
|
formType.value = type |
||||||
|
resetForm() |
||||||
|
// 修改时,设置数据 |
||||||
|
if (id) { |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
formData.value = await UserApi.getUser(id) |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
// 加载部门树 |
||||||
|
deptList.value = handleTree(await DeptApi.getSimpleDeptList({ allFlag: false })) |
||||||
|
// 加载岗位列表 |
||||||
|
roleOptions.value = await RoleApi.getSimpleRoleList() |
||||||
|
} |
||||||
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||||
|
|
||||||
|
/** 提交表单 */ |
||||||
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||||
|
const submitForm = async () => { |
||||||
|
// 校验表单 |
||||||
|
if (!formRef.value) return |
||||||
|
const valid = await formRef.value.validate() |
||||||
|
if (!valid) return |
||||||
|
// 提交请求 |
||||||
|
formLoading.value = true |
||||||
|
try { |
||||||
|
const data = formData.value as unknown as UserApi.UserVO |
||||||
|
if (formType.value === 'create') { |
||||||
|
await UserApi.createUser(data) |
||||||
|
message.success(t('common.createSuccess')) |
||||||
|
} else { |
||||||
|
await UserApi.updateUser(data) |
||||||
|
message.success(t('common.updateSuccess')) |
||||||
|
} |
||||||
|
dialogVisible.value = false |
||||||
|
// 发送操作成功的事件 |
||||||
|
emit('success') |
||||||
|
} finally { |
||||||
|
formLoading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置表单 */ |
||||||
|
const resetForm = () => { |
||||||
|
formData.value = { |
||||||
|
nickname: '', |
||||||
|
deptId: '', |
||||||
|
mobile: '', |
||||||
|
email: '', |
||||||
|
id: undefined, |
||||||
|
username: '', |
||||||
|
password: '', |
||||||
|
sex: 1, |
||||||
|
remark: '', |
||||||
|
status: CommonStatusEnum.ENABLE, |
||||||
|
roleIds: [], |
||||||
|
hireDate: formatDate(new Date(), 'YYYY-MM-DD') |
||||||
|
} |
||||||
|
formRef.value?.resetFields() |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,209 @@ |
|||||||
|
<template> |
||||||
|
<!-- <el-row :gutter="20"> --> |
||||||
|
<!-- 左侧部门树 --> |
||||||
|
<!-- <el-col :span="4" :xs="24"> |
||||||
|
<DeptTree @node-click="handleDeptNodeClick" /> |
||||||
|
</el-col> |
||||||
|
<el-col :span="20" :xs="24"> --> |
||||||
|
<!-- 搜索 --> |
||||||
|
<el-form :model="queryParams" ref="queryFormRef" inline label-width="0"> |
||||||
|
<el-form-item prop="nickname"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.nickname" |
||||||
|
placeholder="请输入姓名" |
||||||
|
clearable |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
class="!w-240px" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="mobile"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.mobile" |
||||||
|
placeholder="请输入手机号码" |
||||||
|
clearable |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
class="!w-240px" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button @click="handleQuery" v-hasPermi="['basic:employee:search']">搜索</el-button> |
||||||
|
<el-button @click="resetQuery" v-hasPermi="['basic:employee:reset']">重置</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
plain |
||||||
|
@click="openForm('create')" |
||||||
|
v-hasPermi="['basic:employee:add']" |
||||||
|
> |
||||||
|
新增 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-form> |
||||||
|
<el-table v-loading="loading" :data="list"> |
||||||
|
<el-table-column label="用户编号" key="id" prop="id" /> |
||||||
|
<el-table-column label="登录账号" prop="username" /> |
||||||
|
<el-table-column label="用户姓名" prop="nickname" /> |
||||||
|
<!-- <el-table-column label="部门" key="deptName" prop="deptName" /> --> |
||||||
|
<el-table-column label="手机号码" prop="mobile" width="120" /> |
||||||
|
<el-table-column label="状态" key="status"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-switch |
||||||
|
v-model="scope.row.status" |
||||||
|
:active-value="0" |
||||||
|
:inactive-value="1" |
||||||
|
active-text="在职" |
||||||
|
inactive-text="离职" |
||||||
|
v-hasPermi="['basic:employee:update']" |
||||||
|
@change="handleStatusChange(scope.row)" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="创建时间" prop="createTime" width="180" :formatter="dateFormatter" /> |
||||||
|
<el-table-column label="操作" width="260"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="openForm('update', scope.row.id)" |
||||||
|
v-hasPermi="['basic:employee:update']" |
||||||
|
> |
||||||
|
修改 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="handleDelete(scope.row.id)" |
||||||
|
v-hasPermi="['basic:employee:delete']" |
||||||
|
> |
||||||
|
删除 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="handleResetPwd(scope.row)" |
||||||
|
v-hasPermi="['basic:employee:password']" |
||||||
|
> |
||||||
|
重置密码 |
||||||
|
</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<Pagination |
||||||
|
:total="total" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
<!-- </el-col> --> |
||||||
|
<!-- </el-row> --> |
||||||
|
|
||||||
|
<!-- 添加或修改用户对话框 --> |
||||||
|
<UserForm ref="formRef" @success="getList" /> |
||||||
|
</template> |
||||||
|
<script setup lang="ts" name="SystemUser"> |
||||||
|
import { CommonStatusEnum } from '@/utils/constants' |
||||||
|
import { dateFormatter } from '@/utils/formatTime' |
||||||
|
import * as UserApi from '@/api/system/user' |
||||||
|
import UserForm from './UserForm.vue' |
||||||
|
// import DeptTree from './DeptTree.vue' |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
const { t } = useI18n() // 国际化 |
||||||
|
|
||||||
|
const loading = ref(true) // 列表的加载中 |
||||||
|
const total = ref(0) // 列表的总页数 |
||||||
|
const list = ref([]) // 列表的数 |
||||||
|
const queryParams = reactive({ |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 10, |
||||||
|
username: undefined, |
||||||
|
nickname: undefined, |
||||||
|
mobile: undefined, |
||||||
|
deptId: undefined |
||||||
|
}) |
||||||
|
const queryFormRef = ref() // 搜索的表单 |
||||||
|
|
||||||
|
/** 查询列表 */ |
||||||
|
const getList = async () => { |
||||||
|
loading.value = true |
||||||
|
try { |
||||||
|
const data = await UserApi.getUserPage(queryParams) |
||||||
|
list.value = data.list |
||||||
|
total.value = data.total |
||||||
|
} finally { |
||||||
|
loading.value = false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 搜索按钮操作 */ |
||||||
|
const handleQuery = () => { |
||||||
|
queryParams.pageNo = 1 |
||||||
|
getList() |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置按钮操作 */ |
||||||
|
const resetQuery = () => { |
||||||
|
queryFormRef.value?.resetFields() |
||||||
|
handleQuery() |
||||||
|
} |
||||||
|
|
||||||
|
// /** 处理部门被点击 */ |
||||||
|
// const handleDeptNodeClick = async (row) => { |
||||||
|
// queryParams.deptId = row.id |
||||||
|
// await getList() |
||||||
|
// } |
||||||
|
|
||||||
|
/** 添加/修改操作 */ |
||||||
|
const formRef = ref() |
||||||
|
const openForm = (type: string, id?: number) => { |
||||||
|
formRef.value.open(type, id) |
||||||
|
} |
||||||
|
|
||||||
|
/** 修改用户状态 */ |
||||||
|
const handleStatusChange = async (row: UserApi.UserVO) => { |
||||||
|
try { |
||||||
|
// 修改状态的二次确认 |
||||||
|
const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用' |
||||||
|
await message.confirm('确认要"' + text + '""' + row.username + '"用户吗?') |
||||||
|
// 发起修改状态 |
||||||
|
await UserApi.updateUserStatus(row.id, row.status) |
||||||
|
// 刷新列表 |
||||||
|
await getList() |
||||||
|
} catch { |
||||||
|
// 取消后,进行恢复按钮 |
||||||
|
row.status = |
||||||
|
row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** 删除按钮操作 */ |
||||||
|
const handleDelete = async (id: number) => { |
||||||
|
try { |
||||||
|
// 删除的二次确认 |
||||||
|
await message.delConfirm() |
||||||
|
// 发起删除 |
||||||
|
await UserApi.deleteUser(id) |
||||||
|
message.success(t('common.delSuccess')) |
||||||
|
// 刷新列表 |
||||||
|
await getList() |
||||||
|
} catch {} |
||||||
|
} |
||||||
|
|
||||||
|
/** 重置密码 */ |
||||||
|
const handleResetPwd = async (row: UserApi.UserVO) => { |
||||||
|
try { |
||||||
|
// 重置的二次确认 |
||||||
|
const result = await message.prompt( |
||||||
|
'请输入"' + row.username + '"的新密码', |
||||||
|
t('common.reminder') |
||||||
|
) |
||||||
|
const password = result.value |
||||||
|
// 发起重置 |
||||||
|
await UserApi.resetUserPwd(row.id, password) |
||||||
|
message.success('修改成功,新密码是:' + password) |
||||||
|
} catch {} |
||||||
|
} |
||||||
|
|
||||||
|
/** 初始化 */ |
||||||
|
onMounted(() => { |
||||||
|
getList() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,344 @@ |
|||||||
|
<template> |
||||||
|
<el-dialog |
||||||
|
title="试题" |
||||||
|
:close-on-click-modal="false" |
||||||
|
append-to-body |
||||||
|
v-model="visible" |
||||||
|
width="900px" |
||||||
|
> |
||||||
|
<div> |
||||||
|
<el-form |
||||||
|
ref="dialogFormRef" |
||||||
|
:model="dialogForm" |
||||||
|
:rules="dataRule" |
||||||
|
label-width="auto" |
||||||
|
label-position="right" |
||||||
|
@keyup.enter="dialogFormSubmit()" |
||||||
|
> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="题目" prop="question"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.question" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入题目" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="题目关键字" prop="titleWords"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.titleWords" |
||||||
|
maxlength="1000" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="专项" prop="categoryTitle"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.categoryTitle" |
||||||
|
maxlength="1000" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="章节" prop="chapter"> |
||||||
|
<el-select v-model="dialogForm.chapter" style="width: 100%"> |
||||||
|
<el-option |
||||||
|
v-for="dict in chapterOptions" |
||||||
|
:key="dict.chapterId" |
||||||
|
:label="dict.chapterName" |
||||||
|
:value="dict.chapterId" |
||||||
|
/> |
||||||
|
</el-select> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
|
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="题型" prop="type"> |
||||||
|
<el-radio-group v-model="dialogForm.type"> |
||||||
|
<el-radio label="1" value="1">判断题</el-radio> |
||||||
|
<el-radio label="2" value="2">单选题</el-radio> |
||||||
|
<el-radio label="3" value="3">多选题</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
|
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="排序" prop="showOrder"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.showOrder" |
||||||
|
maxlength="20" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="选项A" prop="chooseA"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.chooseA" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="选项B" prop="chooseB"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.chooseB" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="选项C" prop="chooseC"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.chooseC" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
<el-col :span="12"> |
||||||
|
<el-form-item label="选项D" prop="chooseD"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.chooseD" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="答案" prop="trueAnswer"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.trueAnswer" |
||||||
|
maxlength="200" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="难点分析" prop="bestAnswer"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.bestAnswer" |
||||||
|
maxlength="1000" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="答题技巧" prop="skillInfo"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.skillInfo" |
||||||
|
maxlength="1000" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
|
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="技巧关键字" prop="skillWords"> |
||||||
|
<el-input |
||||||
|
v-model="dialogForm.skillWords" |
||||||
|
maxlength="1000" |
||||||
|
placeholder="请输入" |
||||||
|
clearable |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="车型" prop="carTypeId"> |
||||||
|
<span v-if="dialogForm.carTypeId == '1001'">小车</span> |
||||||
|
<span v-if="dialogForm.carTypeId == '1002'">摩托车</span> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-col :span="24"> |
||||||
|
<el-form-item label="科目" prop="subject"> |
||||||
|
<span v-if="dialogForm.subject == '1'">科一</span> |
||||||
|
<span v-if="dialogForm.subject == '4'">科四</span> |
||||||
|
</el-form-item> |
||||||
|
</el-col> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-form-item label="题目图片" prop="imageUrl"> |
||||||
|
<el-upload |
||||||
|
action="#" |
||||||
|
accept=".png,.jpg,.jpeg,.gif" |
||||||
|
:limit="1" |
||||||
|
:http-request="handleImport" |
||||||
|
:on-exceed="handleExceed" |
||||||
|
:show-file-list="false" |
||||||
|
> |
||||||
|
<img v-if="imgUrl" :src="imgUrl" style="width: 200px" /> |
||||||
|
<i v-else class="el-icon-plus"></i> |
||||||
|
</el-upload> |
||||||
|
</el-form-item> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
</div> |
||||||
|
<template #footer> |
||||||
|
<span class="dialog-footer"> |
||||||
|
<el-button plain @click="visible = false">取消</el-button> |
||||||
|
<el-button type="primary" :disabled="!canSubmit" @click="dialogFormSubmit()"> |
||||||
|
确定 |
||||||
|
</el-button> |
||||||
|
</span> |
||||||
|
</template> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="QuesAddForm"> |
||||||
|
import { addQuestion, updateQuestion, uploadFile } from '@/api/xjapplet/xjdatabase' |
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const emit = defineEmits(['update']) |
||||||
|
|
||||||
|
const visible = ref(false) |
||||||
|
const canSubmit = ref(true) |
||||||
|
const imgUrl = ref(undefined) |
||||||
|
const chapterOptions = ref([]) |
||||||
|
const dialogForm = ref({ |
||||||
|
id: undefined, |
||||||
|
showOrder: 0, |
||||||
|
categoryTitle: undefined, |
||||||
|
question: undefined, |
||||||
|
bestAnswer: undefined, |
||||||
|
chooseA: undefined, |
||||||
|
chooseB: undefined, |
||||||
|
chooseC: undefined, |
||||||
|
chooseD: undefined, |
||||||
|
imageUrl: undefined, |
||||||
|
type: undefined, |
||||||
|
trueAnswer: undefined, |
||||||
|
carTypeId: undefined, |
||||||
|
skillInfoPic: undefined, |
||||||
|
source: undefined |
||||||
|
}) |
||||||
|
|
||||||
|
const dataRule = { |
||||||
|
schoolName: [{ required: true, message: '驾校名称不能为空', trigger: 'blur' }], |
||||||
|
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] |
||||||
|
} |
||||||
|
|
||||||
|
const open = (info = undefined, opts) => { |
||||||
|
visible.value = true |
||||||
|
chapterOptions.value = opts |
||||||
|
resetDialogForm() |
||||||
|
if (info) { |
||||||
|
dialogForm.value = { ...info, chapter: parseInt(info.chapter) } |
||||||
|
if (dialogForm.value.imageUrl) { |
||||||
|
imgUrl.value = 'https://ss-cloud.ahduima.com/xjxc/pic/' + dialogForm.value.imageUrl |
||||||
|
} |
||||||
|
} |
||||||
|
info.source = info.source |
||||||
|
} |
||||||
|
|
||||||
|
defineExpose({ |
||||||
|
open |
||||||
|
}) |
||||||
|
|
||||||
|
const resetDialogForm = () => { |
||||||
|
dialogForm.value = { |
||||||
|
id: undefined, |
||||||
|
showOrder: 0, |
||||||
|
question: undefined, |
||||||
|
bestAnswer: undefined, |
||||||
|
chooseA: undefined, |
||||||
|
chooseB: undefined, |
||||||
|
chooseC: undefined, |
||||||
|
chooseD: undefined, |
||||||
|
imageUrl: undefined, |
||||||
|
type: undefined, |
||||||
|
trueAnswer: undefined, |
||||||
|
carTypeId: undefined, |
||||||
|
skillInfoPic: undefined, |
||||||
|
skillInfo: undefined, |
||||||
|
jqtp: undefined, |
||||||
|
biaoji: undefined, |
||||||
|
titleWords: undefined, |
||||||
|
skillWords: undefined, |
||||||
|
optaWords: undefined, |
||||||
|
optbWords: undefined, |
||||||
|
optcWords: undefined, |
||||||
|
optdWords: undefined, |
||||||
|
carTypeId: undefined, |
||||||
|
source: undefined |
||||||
|
} |
||||||
|
} |
||||||
|
const dialogFormRef = ref(null) |
||||||
|
// 表单提交 |
||||||
|
const dialogFormSubmit = async () => { |
||||||
|
if (!dialogFormRef.value) return |
||||||
|
const valid = await dialogFormRef.value.validate() |
||||||
|
if (!valid) return |
||||||
|
|
||||||
|
if (dialogForm.value.questionId) { |
||||||
|
updateQuestion(dialogForm.value).then((response) => { |
||||||
|
if (response) { |
||||||
|
message.success('修改成功') |
||||||
|
emit('update') |
||||||
|
visible.value = false |
||||||
|
} |
||||||
|
}) |
||||||
|
} else { |
||||||
|
addQuestion(dialogForm.value).then((response) => { |
||||||
|
if (response) { |
||||||
|
message.success('新增成功') |
||||||
|
visible.value = false |
||||||
|
emit('update') |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
const handleImport = (opt) => { |
||||||
|
const data = new FormData() |
||||||
|
data.append('file', opt.file) |
||||||
|
uploadFile(data).then((resp) => { |
||||||
|
if (resp.code == 200) { |
||||||
|
message.success('文件上传成功') |
||||||
|
dialogForm.value.imageUrl = resp.data |
||||||
|
imgUrl.value = 'https://ss-cloud.ahduima.com/xjxc/pic/' + dialogForm.value.imageUrl |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
const handleExceed = (files) => { |
||||||
|
handleImport({ file: files[0] }) |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,228 @@ |
|||||||
|
<template> |
||||||
|
<div class="app-container" style="text-align: center"> |
||||||
|
<el-tabs v-model="queryParams.source" @tab-click="handleChangeSource"> |
||||||
|
<el-tab-pane |
||||||
|
v-for="item in sourceOptions" |
||||||
|
:key="item.key" |
||||||
|
:label="item.label" |
||||||
|
:name="item.key" |
||||||
|
> |
||||||
|
<el-form :inline="true" label-width="68px" @submit.prevent> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-form-item label="车型"> |
||||||
|
<el-radio-group v-model="queryParams.carTypeId" @change="getQuestionChapter"> |
||||||
|
<el-radio label="1001" value="1001">小车</el-radio> |
||||||
|
<el-radio label="1002" value="1002">摩托车</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="科目"> |
||||||
|
<el-radio-group v-model="queryParams.subject" @change="getQuestionChapter"> |
||||||
|
<el-radio label="1" value="1">科一</el-radio> |
||||||
|
<el-radio label="4" value="4">科四</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
|
||||||
|
<el-form-item label="有图片"> |
||||||
|
<el-radio-group v-model="queryParams.isPic"> |
||||||
|
<el-radio :label="true" :value="true">有</el-radio> |
||||||
|
<el-radio :label="false" :value="false">无</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</el-row> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-form-item label="题目"> |
||||||
|
<el-input |
||||||
|
v-model="queryParams.question" |
||||||
|
placeholder="请输入题目" |
||||||
|
clearable |
||||||
|
style="width: 400px" |
||||||
|
@keyup.enter="handleQuery" |
||||||
|
/> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
@click="handleQuery" |
||||||
|
v-hasPermi="['question:database:search']" |
||||||
|
> |
||||||
|
搜索 |
||||||
|
</el-button> |
||||||
|
<el-button type="primary" @click="handleAdd" v-hasPermi="['question:database:add']"> |
||||||
|
新增 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
|
||||||
|
<el-table |
||||||
|
v-loading="loading" |
||||||
|
:data="tableList" |
||||||
|
highlight-current-row |
||||||
|
max-height="calc(100vh - 260px)" |
||||||
|
> |
||||||
|
<el-table-column type="index" width="55" align="center" /> |
||||||
|
<el-table-column label="题目" align="left" prop="question" min-width="140" /> |
||||||
|
<el-table-column label="选项" align="left" min-width="140"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<p v-if="row.chooseA">A:{{ row.chooseA }}</p> |
||||||
|
<p v-if="row.chooseB">B:{{ row.chooseB }}</p> |
||||||
|
<p v-if="row.chooseC">C:{{ row.chooseC }}</p> |
||||||
|
<p v-if="row.chooseD">D:{{ row.chooseD }}</p> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="答案" align="center" prop="trueAnswer" width="100" /> |
||||||
|
<el-table-column label="科目" align="center" prop="subject" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span v-if="row.subject == '1'">科一</span> |
||||||
|
<span v-if="row.subject == '4'">科四</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="章节" align="center" prop="chapterName" min-width="100" /> |
||||||
|
<el-table-column label="图片" align="center" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-image |
||||||
|
v-if="row.imageUrl" |
||||||
|
:src="`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`" |
||||||
|
:preview-src-list="[`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`]" |
||||||
|
:lazy="true" |
||||||
|
style="width: 80px" |
||||||
|
preview-teleported |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="状态" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-tag v-if="row.isActive == 0" type="success">使用中</el-tag> |
||||||
|
<el-tag v-else type="danger">已删除</el-tag> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column label="操作" align="center" width="140"> |
||||||
|
<template #default="scope"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="handleEdit(scope.row)" |
||||||
|
v-hasPermi="['question:database:edit']" |
||||||
|
> |
||||||
|
修改 |
||||||
|
</el-button> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="handleDelete(scope.row.id)" |
||||||
|
v-hasPermi="['question:database:remove']" |
||||||
|
> |
||||||
|
删除 |
||||||
|
</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
|
||||||
|
<pagination |
||||||
|
v-show="total > 0" |
||||||
|
:total="total" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
@pagination="getList" |
||||||
|
/> |
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
|
||||||
|
<QuestionAddForm ref="dialogAddForm" @update="getList" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="XjDatabase"> |
||||||
|
import { searchQuestion, deleteQuestion, getQuestionSort } from '@/api/xjapplet/xjdatabase' |
||||||
|
import QuestionAddForm from './components/QuestionAddForm.vue' |
||||||
|
|
||||||
|
const loading = ref(false) |
||||||
|
const total = ref(0) |
||||||
|
const tableList = ref([]) |
||||||
|
const queryParams = ref({ |
||||||
|
source: '1', |
||||||
|
question: '', |
||||||
|
carTypeId: '1001', |
||||||
|
subject: '1', |
||||||
|
isPic: undefined, |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 100 |
||||||
|
}) |
||||||
|
|
||||||
|
const sourceOptions = [ |
||||||
|
{ |
||||||
|
key: '1', |
||||||
|
label: '驾考精灵' |
||||||
|
}, |
||||||
|
{ |
||||||
|
key: '2', |
||||||
|
label: '驾校一点通' |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
getQuestionChapter() |
||||||
|
}) |
||||||
|
|
||||||
|
const chapterOptions = ref([]) |
||||||
|
const getQuestionChapter = () => { |
||||||
|
getQuestionSort({ |
||||||
|
carTypeId: queryParams.value.carTypeId, |
||||||
|
subject: queryParams.value.subject, |
||||||
|
source: queryParams.value.source |
||||||
|
}).then((data) => { |
||||||
|
chapterOptions.value = data |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function getList() { |
||||||
|
loading.value = true |
||||||
|
searchQuestion(queryParams.value).then((response) => { |
||||||
|
tableList.value = response.list |
||||||
|
total.value = response.total |
||||||
|
loading.value = false |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function handleQuery() { |
||||||
|
getList() |
||||||
|
} |
||||||
|
|
||||||
|
const dialogAddForm = ref(null) |
||||||
|
function handleEdit(item) { |
||||||
|
dialogAddForm.value.open(item, chapterOptions.value) |
||||||
|
} |
||||||
|
|
||||||
|
function handleAdd() { |
||||||
|
dialogAddForm.value.open( |
||||||
|
{ |
||||||
|
subject: queryParams.value.subject, |
||||||
|
carTypeId: queryParams.value.carTypeId, |
||||||
|
source: queryParams.value.source |
||||||
|
}, |
||||||
|
chapterOptions.value |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
function handleDelete(id) { |
||||||
|
deleteQuestion(id).then(() => { |
||||||
|
getList() |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function handleChangeSource() { |
||||||
|
const obj = { |
||||||
|
question: '', |
||||||
|
carTypeId: '1001', |
||||||
|
subject: '1', |
||||||
|
isPic: undefined, |
||||||
|
pageNo: 1 |
||||||
|
} |
||||||
|
queryParams.value = { ...obj, source: queryParams.value.source } |
||||||
|
getQuestionChapter() |
||||||
|
getList() |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,7 @@ |
|||||||
|
<template> |
||||||
|
<div> 基础设置 </div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="QuestionSetting"></script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,7 @@ |
|||||||
|
<template> |
||||||
|
<div> 无人机题库 </div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="UAV"></script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,7 @@ |
|||||||
|
<template> |
||||||
|
<div> 无人机VIP </div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="UAVVip"></script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,310 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-form inline label-width="68px" @submit.prevent> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-form-item label="车型" @change="searchMj"> |
||||||
|
<el-radio-group v-model="queryParams.carTypeId"> |
||||||
|
<el-radio label="1001" value="1001">小车</el-radio> |
||||||
|
<el-radio label="1002" value="1002">摩托车</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="科目"> |
||||||
|
<el-radio-group v-model="queryParams.subject" @change="searchMj"> |
||||||
|
<el-radio label="1" value="1">科一</el-radio> |
||||||
|
<el-radio label="4" value="4">科四</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<div style="display: flex; padding: 10px; border: 1px solid #eee; height: calc(100vh - 80px)"> |
||||||
|
<div style="width: 300px; border-right: 1px solid #eee"> |
||||||
|
<div style="display: flex; justify-content: space-between; padding-right: 20px"> |
||||||
|
<div style="font-size: 18px; font-weight: bold">密卷</div> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="addMjItem" |
||||||
|
v-hasPermi="['questiont:vip-data:mj:add']" |
||||||
|
>新增</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<el-radio-group |
||||||
|
v-model="mjIndex" |
||||||
|
style="width: 100%; display: block; margin-top: 20px" |
||||||
|
@change="getQuestionList" |
||||||
|
> |
||||||
|
<el-radio v-for="(item, index) in mjList" :key="index" :label="index" class="flex-radio"> |
||||||
|
<div style="flex: 1; width: 100px">{{ getMjTitle(index) }}</div> |
||||||
|
<div style="padding-right: 15px"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="removeMj(item)" |
||||||
|
v-hasPermi="['questiont:vip-data:mj:remove']" |
||||||
|
>删除</el-button |
||||||
|
> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="clearMjDetail(item)" |
||||||
|
v-hasPermi="['questiont:vip-data:mj:clear']" |
||||||
|
>清空</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</div> |
||||||
|
<div style="flex: 1; padding-left: 20px; padding-right: 20px"> |
||||||
|
<div |
||||||
|
v-if="mjList.length > 0" |
||||||
|
style="display: flex; justify-content: space-between; align-items: center" |
||||||
|
> |
||||||
|
<div style="font-size: 20px; font-weight: bold"> |
||||||
|
当前密卷:{{ getMjTitle(mjIndex) }} |
||||||
|
</div> |
||||||
|
<div style="margin-left: 10px; margin-right: 10px"> 题目数:{{ tableList.length }} </div> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
@click="addMjDetail" |
||||||
|
v-hasPermi="['questiont:vip-data:mj:add-question']" |
||||||
|
>新增密卷试题</el-button |
||||||
|
> |
||||||
|
</div> |
||||||
|
<el-table |
||||||
|
v-loading="loading" |
||||||
|
:data="tableList" |
||||||
|
style="margin-top: 10px" |
||||||
|
max-height="calc(100vh - 280px)" |
||||||
|
> |
||||||
|
<el-table-column type="index" width="55" align="center" /> |
||||||
|
<el-table-column label="题目" align="left" prop="question" min-width="140" /> |
||||||
|
<el-table-column label="选项" align="left" min-width="140"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<p v-if="row.chooseA">A:{{ row.chooseA }}</p> |
||||||
|
<p v-if="row.chooseB">B:{{ row.chooseB }}</p> |
||||||
|
<p v-if="row.chooseC">C:{{ row.chooseC }}</p> |
||||||
|
<p v-if="row.chooseD">D:{{ row.chooseD }}</p> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="答案" align="center" prop="trueAnswer" width="100" /> |
||||||
|
<el-table-column label="科目" align="center" prop="subject" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span v-if="row.subject == '1'">科一</span> |
||||||
|
<span v-if="row.subject == '4'">科四</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="章节" align="center" prop="chapterName" min-width="100" /> |
||||||
|
<el-table-column label="图片" align="center" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-image |
||||||
|
v-if="row.imageUrl" |
||||||
|
:src="`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`" |
||||||
|
:preview-src-list="[`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`]" |
||||||
|
:lazy="true" |
||||||
|
style="width: 80px" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
|
||||||
|
<el-table-column label="操作" align="center" width="100px"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="takeoutMj(row)" |
||||||
|
v-hasPermi="['questiont:vip-data:mj:remove-question']" |
||||||
|
>移出密卷</el-button |
||||||
|
> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog v-model="showDialog" title="新增试题" width="80%"> |
||||||
|
<div style="display: flex; align-items: center; margin-bottom: 20px"> |
||||||
|
<el-input v-model="quesName" placeholder="请输入题目" clearable @keyup.enter="searchQues" /> |
||||||
|
<el-button style="margin-left: 20px" type="primary" @click="searchQues">搜索</el-button> |
||||||
|
</div> |
||||||
|
<el-table :data="quesLit" highlight-current-row height="calc(100vh - 260px)"> |
||||||
|
<el-table-column label="题目" align="left" prop="question" min-width="140" /> |
||||||
|
<el-table-column label="选项" align="left" min-width="140"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<p v-if="row.chooseA">A:{{ row.chooseA }}</p> |
||||||
|
<p v-if="row.chooseB">B:{{ row.chooseB }}</p> |
||||||
|
<p v-if="row.chooseC">C:{{ row.chooseC }}</p> |
||||||
|
<p v-if="row.chooseD">D:{{ row.chooseD }}</p> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="答案" align="center" prop="trueAnswer" width="100" /> |
||||||
|
<el-table-column label="章节" align="center" prop="chapterName" min-width="100" /> |
||||||
|
<el-table-column label="图片" align="center" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-image |
||||||
|
v-if="row.imageUrl" |
||||||
|
:src="`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`" |
||||||
|
:preview-src-list="[`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`]" |
||||||
|
:lazy="true" |
||||||
|
style="width: 80px" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="100px"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button type="primary" link @click="sureAddQues(row)">加入密卷</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="SimpleData"> |
||||||
|
import { |
||||||
|
getMjList, |
||||||
|
addMj, |
||||||
|
delMj, |
||||||
|
clearMj, |
||||||
|
getMjQuestionList, |
||||||
|
addMjQuestion, |
||||||
|
delMjQuestion |
||||||
|
} from '@/api/xjapplet/vipdatabase.js' |
||||||
|
import { searchQuestion } from '@/api/xjapplet/xjdatabase.js' |
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
source: { |
||||||
|
type: String, |
||||||
|
default: '1' |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
watch( |
||||||
|
() => props.source, |
||||||
|
(newValue) => { |
||||||
|
queryParams.value.source = newValue |
||||||
|
searchMj() |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
const queryParams = ref({ |
||||||
|
carTypeId: '1001', |
||||||
|
subject: '1' |
||||||
|
}) |
||||||
|
const mjIndex = ref(0) |
||||||
|
const mjList = ref([]) |
||||||
|
const loading = ref(false) |
||||||
|
const tableList = ref([]) |
||||||
|
const showDialog = ref(false) |
||||||
|
const quesName = ref('') |
||||||
|
const quesLit = ref([]) |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
searchMj() |
||||||
|
}) |
||||||
|
|
||||||
|
function addMjItem() { |
||||||
|
addMj(queryParams.value).then((res) => { |
||||||
|
if (res) { |
||||||
|
searchMj() |
||||||
|
message.success('添加成功') |
||||||
|
} else { |
||||||
|
message.error('添加失败') |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
function getMjTitle(idx) { |
||||||
|
// const cjObj = { |
||||||
|
// 1001: '小车', |
||||||
|
// 1002: '摩托车' |
||||||
|
// } |
||||||
|
// const kmObj = { |
||||||
|
// 1: '科一', |
||||||
|
// 4: '科四' |
||||||
|
// } |
||||||
|
// return `${cjObj[queryParams.value.carTypeId]}${kmObj[queryParams.value.subject]}考前密卷 第${ |
||||||
|
// idx + 1 |
||||||
|
// }套` |
||||||
|
return `考前密卷 第${idx + 1}套` |
||||||
|
} |
||||||
|
function removeMj(item) { |
||||||
|
message |
||||||
|
.confirm('是否确认删除密卷?') |
||||||
|
.then(function () { |
||||||
|
return delMj(item.secretId) |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
searchMj() |
||||||
|
message.success('删除成功') |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
function clearMjDetail(item) { |
||||||
|
message |
||||||
|
.confirm('是否确认清空密卷题目?') |
||||||
|
.then(function () { |
||||||
|
return clearMj(item.secretId) |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
getQuestionList() |
||||||
|
message.success('清空题目成功') |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
function searchMj() { |
||||||
|
getMjList(queryParams.value).then((resp) => { |
||||||
|
mjList.value = resp || [] |
||||||
|
if (mjList.value.length > 0) { |
||||||
|
mjIndex.value = 0 |
||||||
|
getQuestionList() |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
function addMjDetail() { |
||||||
|
showDialog.value = true |
||||||
|
} |
||||||
|
function searchQues() { |
||||||
|
searchQuestion({ |
||||||
|
...queryParams.value, |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 1000, |
||||||
|
question: quesName.value |
||||||
|
}).then((response) => { |
||||||
|
quesLit.value = response.list |
||||||
|
}) |
||||||
|
} |
||||||
|
function takeoutMj(row) { |
||||||
|
message |
||||||
|
.confirm('是否确认将该题移出密卷?') |
||||||
|
.then(function () { |
||||||
|
return delMjQuestion(row.id) |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
getQuestionList() |
||||||
|
message.success('清空题目成功') |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
function getQuestionList() { |
||||||
|
getMjQuestionList({ |
||||||
|
secretId: mjList.value[mjIndex.value].secretId |
||||||
|
}).then((resp) => { |
||||||
|
tableList.value = resp |
||||||
|
}) |
||||||
|
} |
||||||
|
function sureAddQues(row) { |
||||||
|
addMjQuestion({ |
||||||
|
secretId: mjList.value[mjIndex.value].secretId, |
||||||
|
subId: row.subId |
||||||
|
}) |
||||||
|
.then((resp) => { |
||||||
|
if (resp) { |
||||||
|
message.success('添加成功') |
||||||
|
getQuestionList() |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,211 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-form inline label-width="68px" @submit.prevent> |
||||||
|
<el-row :gutter="20"> |
||||||
|
<el-form-item label="车型"> |
||||||
|
<el-radio-group v-model="queryParams.carTypeId"> |
||||||
|
<el-radio label="1001" value="1001">小车</el-radio> |
||||||
|
<el-radio label="1002" value="1002">摩托车</el-radio> |
||||||
|
<!-- <el-radio label="B2">货车</el-radio> --> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item label="科目"> |
||||||
|
<el-radio-group v-model="queryParams.subject"> |
||||||
|
<el-radio label="1" value="1">科一</el-radio> |
||||||
|
<el-radio label="4" value="4">科四</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item> |
||||||
|
<el-button |
||||||
|
type="primary" |
||||||
|
v-hasPermi="['question:vip-data:jx:search']" |
||||||
|
@click=" |
||||||
|
() => { |
||||||
|
queryParams.pageNo = 1 |
||||||
|
getQuestionList() |
||||||
|
} |
||||||
|
" |
||||||
|
> |
||||||
|
查询 |
||||||
|
</el-button> |
||||||
|
<el-button type="primary" @click="addMjDetail" v-hasPermi="['question:vip-data:jx:add']"> |
||||||
|
新增精选试题 |
||||||
|
</el-button> |
||||||
|
</el-form-item> |
||||||
|
</el-row> |
||||||
|
</el-form> |
||||||
|
<el-table v-loading="loading" :data="tableList" height="calc(100vh - 250px)"> |
||||||
|
<el-table-column type="index" width="55" align="center" /> |
||||||
|
<el-table-column label="题目" align="left" prop="question" min-width="140" /> |
||||||
|
<el-table-column label="选项" align="left" min-width="140"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<p v-if="row.chooseA">A:{{ row.chooseA }}</p> |
||||||
|
<p v-if="row.chooseB">B:{{ row.chooseB }}</p> |
||||||
|
<p v-if="row.chooseC">C:{{ row.chooseC }}</p> |
||||||
|
<p v-if="row.chooseD">D:{{ row.chooseD }}</p> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="答案" align="center" prop="trueAnswer" width="100" /> |
||||||
|
<el-table-column label="科目" align="center" prop="subject" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<span v-if="row.subject == '1'">科一</span> |
||||||
|
<span v-if="row.subject == '4'">科四</span> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="图片" align="center" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-image |
||||||
|
v-if="row.imageUrl" |
||||||
|
:src="`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`" |
||||||
|
:preview-src-list="[`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`]" |
||||||
|
:lazy="true" |
||||||
|
style="width: 80px" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" align="center" width="100px"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button |
||||||
|
size="small" |
||||||
|
type="primary" |
||||||
|
link |
||||||
|
@click="takeoutMj(row)" |
||||||
|
v-hasPermi="['question:vip-data:jx:remove']" |
||||||
|
> |
||||||
|
移出精选 |
||||||
|
</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
<pagination |
||||||
|
v-show="total > 0" |
||||||
|
:total="total" |
||||||
|
v-model:page="queryParams.pageNo" |
||||||
|
v-model:limit="queryParams.pageSize" |
||||||
|
@pagination="getQuestionList" |
||||||
|
/> |
||||||
|
|
||||||
|
<el-dialog v-model="showDialog" title="新增试题" width="80%"> |
||||||
|
<div style="display: flex; align-items: center; margin-bottom: 20px"> |
||||||
|
<el-input v-model="quesName" placeholder="请输入题目" clearable @keyup.enter="searchQues" /> |
||||||
|
<el-button style="margin-left: 20px" type="primary" @click="searchQues">搜索</el-button> |
||||||
|
</div> |
||||||
|
<el-table :data="quesLit" highlight-current-row height="calc(100vh - 260px)"> |
||||||
|
<el-table-column label="题目" align="left" prop="question" min-width="140" /> |
||||||
|
<el-table-column label="选项" align="left" min-width="140"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<p v-if="row.chooseA">A:{{ row.chooseA }}</p> |
||||||
|
<p v-if="row.chooseB">B:{{ row.chooseB }}</p> |
||||||
|
<p v-if="row.chooseC">C:{{ row.chooseC }}</p> |
||||||
|
<p v-if="row.chooseD">D:{{ row.chooseD }}</p> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="答案" align="center" prop="trueAnswer" width="100" /> |
||||||
|
<el-table-column label="章节" align="center" prop="chapterName" min-width="100" /> |
||||||
|
<el-table-column label="图片" align="center" width="100"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-image |
||||||
|
v-if="row.imageUrl" |
||||||
|
:src="`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`" |
||||||
|
:preview-src-list="[`https://ss-cloud.ahduima.com/xjxc/pic/${row.imageUrl}`]" |
||||||
|
:lazy="true" |
||||||
|
style="width: 80px" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="操作" width="100px"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-button type="primary" link @click="sureAddQues(row)">加入精选</el-button> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
</el-table> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="SimpleData"> |
||||||
|
import { getJxQuestionList, addJx, delJxData } from '@/api/xjapplet/vipdatabase.js' |
||||||
|
import { searchQuestion } from '@/api/xjapplet/xjdatabase.js' |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
source: { |
||||||
|
type: String, |
||||||
|
default: '1' |
||||||
|
} |
||||||
|
}) |
||||||
|
watch( |
||||||
|
() => props.source, |
||||||
|
(newValue) => { |
||||||
|
queryParams.value.source = newValue |
||||||
|
getQuestionList() |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗 |
||||||
|
|
||||||
|
const queryParams = ref({ |
||||||
|
carTypeId: '1001', |
||||||
|
subject: '1', |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 100 |
||||||
|
}) |
||||||
|
|
||||||
|
const total = ref(0) |
||||||
|
|
||||||
|
const loading = ref(false) |
||||||
|
const tableList = ref([]) |
||||||
|
const showDialog = ref(false) |
||||||
|
const quesName = ref('') |
||||||
|
const quesLit = ref([]) |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
getQuestionList() |
||||||
|
}) |
||||||
|
function addMjDetail() { |
||||||
|
showDialog.value = true |
||||||
|
} |
||||||
|
function searchQues() { |
||||||
|
searchQuestion({ |
||||||
|
...queryParams.value, |
||||||
|
pageNo: 1, |
||||||
|
pageSize: 1000, |
||||||
|
question: quesName.value |
||||||
|
}).then((response) => { |
||||||
|
quesLit.value = response.list |
||||||
|
}) |
||||||
|
} |
||||||
|
function takeoutMj(row) { |
||||||
|
message |
||||||
|
.confirm('是否确认将该题移出精选?') |
||||||
|
.then(function () { |
||||||
|
return delJxData(row.id) |
||||||
|
}) |
||||||
|
.then(() => { |
||||||
|
getQuestionList() |
||||||
|
message.success('清空题目成功') |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
function getQuestionList() { |
||||||
|
getJxQuestionList(queryParams.value).then((resp) => { |
||||||
|
tableList.value = resp.list |
||||||
|
total.value = resp.total |
||||||
|
}) |
||||||
|
} |
||||||
|
function sureAddQues(row) { |
||||||
|
addJx({ |
||||||
|
questionId: row.questionId, |
||||||
|
carTypeId: queryParams.value.carTypeId, |
||||||
|
subject: queryParams.value.subject |
||||||
|
}) |
||||||
|
.then((resp) => { |
||||||
|
if (resp) { |
||||||
|
message.success('添加成功') |
||||||
|
getQuestionList() |
||||||
|
} |
||||||
|
}) |
||||||
|
.catch(() => {}) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,30 @@ |
|||||||
|
<template> |
||||||
|
<el-tabs v-model="source" @tab-click="handleChangeSource"> |
||||||
|
<el-tab-pane v-for="item in sourceOptions" :key="item.key" :label="item.label" :name="item.key"> |
||||||
|
<el-tabs v-model="tabIndex" tab-position="left" style="height: 400px" class="profile-tabs"> |
||||||
|
<el-tab-pane label="精选题" :name="1" v-if="checkPermi(['question:vip-data:jx'])"> |
||||||
|
<SimpleData v-if="tabIndex == 1" :source="source" /> |
||||||
|
</el-tab-pane> |
||||||
|
<el-tab-pane label="密卷" :name="2" v-if="checkPermi(['question:vip-data:mj'])"> |
||||||
|
<SecretData v-if="tabIndex == 2" :source="source" /> |
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
</el-tab-pane> |
||||||
|
</el-tabs> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="VipData"> |
||||||
|
import { checkPermi } from '@/utils/permission' |
||||||
|
import SimpleData from './conponents/SimpleData.vue' |
||||||
|
import SecretData from './conponents/SecretData.vue' |
||||||
|
|
||||||
|
const tabIndex = ref(1) |
||||||
|
const source = ref('1') |
||||||
|
const sourceOptions = [ |
||||||
|
{ key: '1', label: '驾考精灵' }, |
||||||
|
{ key: '2', label: '驾校一点通' } |
||||||
|
] |
||||||
|
const handleChangeSource = () => {} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
Loading…
Reference in new issue