提交 47613f2f authored 作者: matian's avatar matian

代码提交

上级 646dce9a
......@@ -38,6 +38,8 @@
"ignorableWatch": true,
"inject": true,
"isDefined": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"logicAnd": true,
......@@ -235,6 +237,8 @@
"watchIgnorable": true,
"watchOnce": true,
"watchPausable": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"watchThrottled": true,
"watchWithFilter": true,
"whenever": true
......
......@@ -39,6 +39,8 @@ declare global {
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const logicAnd: typeof import('@vueuse/core')['logicAnd']
......@@ -236,6 +238,8 @@ declare global {
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
......
......@@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
"name": "center-resource",
"version": "0.0.0",
"dependencies": {
"@element-plus/icons-vue": "^1.1.4",
......@@ -35,7 +36,7 @@
"sass": "^1.52.1",
"sortablejs": "^1.15.0",
"typescript": "~4.7.2",
"unplugin-auto-import": "^0.8.5",
"unplugin-auto-import": "^0.8.7",
"vite": "^2.9.9",
"vite-plugin-checker": "^0.4.6",
"vue-tsc": "^0.34.16"
......@@ -4027,6 +4028,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-literal": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.3.0.tgz",
"integrity": "sha512-J+lfm3Pw5nzURj2B8acyvUSBqs3JbjM8WAfrmeH3qcn32+ew6kFwbZFV9+X8k9UOIAkQw9WPSzFZy3083c7l5Q==",
"dev": true,
"dependencies": {
"acorn": "^8.7.1"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
......@@ -4193,9 +4206,9 @@
}
},
"node_modules/unimport": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.4.tgz",
"integrity": "sha512-7OEUIlZMS1s1h1uFAGkCPylMtE8hnlJ/cFurJQHdzKAqIyuGiOREFKaCLbkNtFloZicCpRAlqC0Ny2yMoz6mFg==",
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.6.tgz",
"integrity": "sha512-4cOokUIEvaXAfVCHH87vR+wdKI1KDzxQREW9oi0r6J68TPFEeGLHHc2pdyL0uNDUMd2aLxUikhWARNfoQKqC4Q==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^4.2.1",
......@@ -4206,6 +4219,7 @@
"mlly": "^0.5.2",
"pathe": "^0.3.0",
"scule": "^0.2.1",
"strip-literal": "^0.3.0",
"unplugin": "^0.6.3"
}
},
......@@ -4283,16 +4297,16 @@
}
},
"node_modules/unplugin-auto-import": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.5.tgz",
"integrity": "sha512-JT43zA89fMjxtdqz+sTSkTsL9J0PNdnGmMOvcwbkpDi45yL5SU0aDCZgj0E8+qWLyQSIvvBaDBW3VuBrcc2MXg==",
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.7.tgz",
"integrity": "sha512-xepkl/lzlPmWym/ZqjgKpev30S5402qZYHnRZ7MQ78+WxBykvUw69PB0awWcWJ7atswNs6LkDRpGNqzjFCEH4w==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.5.2",
"@rollup/pluginutils": "^4.2.1",
"local-pkg": "^0.4.1",
"magic-string": "^0.26.2",
"unimport": "^0.2.4",
"unimport": "^0.2.5",
"unplugin": "^0.6.3"
},
"engines": {
......@@ -7674,6 +7688,15 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"strip-literal": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-0.3.0.tgz",
"integrity": "sha512-J+lfm3Pw5nzURj2B8acyvUSBqs3JbjM8WAfrmeH3qcn32+ew6kFwbZFV9+X8k9UOIAkQw9WPSzFZy3083c7l5Q==",
"dev": true,
"requires": {
"acorn": "^8.7.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
......@@ -7797,9 +7820,9 @@
}
},
"unimport": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.4.tgz",
"integrity": "sha512-7OEUIlZMS1s1h1uFAGkCPylMtE8hnlJ/cFurJQHdzKAqIyuGiOREFKaCLbkNtFloZicCpRAlqC0Ny2yMoz6mFg==",
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/unimport/-/unimport-0.2.6.tgz",
"integrity": "sha512-4cOokUIEvaXAfVCHH87vR+wdKI1KDzxQREW9oi0r6J68TPFEeGLHHc2pdyL0uNDUMd2aLxUikhWARNfoQKqC4Q==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^4.2.1",
......@@ -7810,6 +7833,7 @@
"mlly": "^0.5.2",
"pathe": "^0.3.0",
"scule": "^0.2.1",
"strip-literal": "^0.3.0",
"unplugin": "^0.6.3"
},
"dependencies": {
......@@ -7854,16 +7878,16 @@
}
},
"unplugin-auto-import": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.5.tgz",
"integrity": "sha512-JT43zA89fMjxtdqz+sTSkTsL9J0PNdnGmMOvcwbkpDi45yL5SU0aDCZgj0E8+qWLyQSIvvBaDBW3VuBrcc2MXg==",
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-0.8.7.tgz",
"integrity": "sha512-xepkl/lzlPmWym/ZqjgKpev30S5402qZYHnRZ7MQ78+WxBykvUw69PB0awWcWJ7atswNs6LkDRpGNqzjFCEH4w==",
"dev": true,
"requires": {
"@antfu/utils": "^0.5.2",
"@rollup/pluginutils": "^4.2.1",
"local-pkg": "^0.4.1",
"magic-string": "^0.26.2",
"unimport": "^0.2.4",
"unimport": "^0.2.5",
"unplugin": "^0.6.3"
},
"dependencies": {
......
......@@ -40,7 +40,7 @@
"sass": "^1.52.1",
"sortablejs": "^1.15.0",
"typescript": "~4.7.2",
"unplugin-auto-import": "^0.8.5",
"unplugin-auto-import": "^0.8.7",
"vite": "^2.9.9",
"vite-plugin-checker": "^0.4.6",
"vue-tsc": "^0.34.16"
......
......@@ -32,5 +32,9 @@ export function uploadFile(data: Record<string, any>) {
// 删除评论
export function deleteComment(data: { id: string }) {
return httpRequest.post('/api/psp/backend/comment/delete', data)
return httpRequest.post('/api/resource/backend/comment/delete', data)
}
// 获取公共字典列表
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
}
......@@ -33,8 +33,7 @@ const tableRef = ref()
const dataList = ref<any[]>([])
const page = reactive({ total: 0, size: props.limit, currentPage: 1 })
const params = reactive({ page: page.currentPage, page_size: page.size, ...props.remote?.params })
const params = reactive({ page: page.currentPage, ['per-page']: page.size, ...props.remote?.params })
watch(
() => props.data,
list => {
......@@ -59,7 +58,7 @@ const fetchList = (isReset = false) => {
// 翻页参数设置
if (props.hasPagination) {
requestParams.page = page.currentPage
requestParams.page_size = page.size
requestParams['per-page'] = page.size
}
// 接口请求之前
if (beforeRequest) {
......@@ -134,10 +133,27 @@ defineExpose({ refetch })
</template>
<template v-else>
<!-- input -->
<el-input v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'input'" />
<el-input
v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
v-if="item.type === 'input'"
/>
<!-- select -->
<el-select v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'select'">
<el-option :label="option[item.labelKey] || option.label" :value="option[item.valueKey] || option.value" v-for="(option, index) in item.options" :key="index" />
<el-select
v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
v-if="item.type === 'select'"
>
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
v-for="(option, index) in item.options"
:key="index"
/>
</el-select>
</template>
</el-form-item>
......
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
// 获取分类列表
export function getCategoryList(params: { type: string; category_name?: string }) {
return httpRequest.get('/api/resource/v1/backend/category/list', { params })
}
// 新建分类
export function createCategory(data: {
category_name: string
depth?: string
status: string
need_pass: string
parent_id: string
}) {
return httpRequest.post('/api/resource/v1/backend/category/create', data)
}
// 编辑分类
export function updateCategory(data: {
id: string
category_name: string
depth?: string
status: string
need_pass: string
parent_id: string
}) {
return httpRequest.post('/api/resource/v1/backend/category/update', data)
}
// 删除分类
export function delCategory(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/category/delete', data)
}
// 移动分类
export function moveCategory(data: { id: string; brother_id: string; type: string }) {
return httpRequest.post('/api/resource/v1/backend/category/drag', data)
}
......@@ -2,14 +2,29 @@
import { Search } from '@element-plus/icons-vue'
import type { FormRules } from 'element-plus'
import TreeDialog from './TreeDialog.vue'
import { useMapStore } from '@/stores/map'
const categoryName = ref('')
const store = useMapStore()
const isTreeVisible = ref(false)
const formRef = ref()
interface mapList {
label: string
value: string
data_dictionary_id: string
sort: string
remark: string
id: string
}
let classList = $ref<mapList[]>([])
let statusList = $ref<mapList[]>([])
const categoryForm = reactive({
category: '',
hierarchy: 1,
parent_id: '',
category_name: '',
depth: 1,
name: '',
status: '0',
isCourse: '1'
need_pass: '1'
})
const rules = reactive<FormRules>({
name: [
......@@ -29,10 +44,15 @@ const props = defineProps({
isEdit: {
type: Boolean,
required: true
},
title: {
type: String,
required: true
}
})
const emit = defineEmits<{
(e: 'update:dialogVisible', dialogVisible: false): void
(e: 'confirm', categoryForm: any): void
}>()
// 打开类别选择弹框
......@@ -42,8 +62,9 @@ const handleOpenTree = () => {
// 获取子组件确定之后节点回显
const getCheckedLabel = (val: any) => {
console.log(val, '99991111')
categoryForm.category = val.checkedLabel.value
categoryForm.hierarchy = val.checkedLevel.value + 1
categoryName.value = val.checkedCategory.checkedLabel
categoryForm.parent_id = val.checkedCategory.checkedId
categoryForm.depth = val.checkedCategory.checkedLevel
}
// 关闭弹框
const handleCancel = () => {
......@@ -53,26 +74,40 @@ const handleCancel = () => {
}
// 确认提交表单
const handleConfirm = () => {
console.log(categoryForm, '0000')
console.log(categoryForm.parent_id, '0000')
emit('update:dialogVisible', false)
emit('confirm', categoryForm)
if (props.isEdit) {
emit('confirm', { categoryForm, isUpdate: 1, id: props.editData.id })
} else {
emit('confirm', { categoryForm, isUpdate: 0 })
}
}
const getMapList = async () => {
await store.getMapList()
classList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
}
onMounted(() => {
categoryForm.category = props.editData.name
categoryForm.hierarchy = props.editData.hierarchy + 1
console.log(props.editData, 'props.editData111')
getMapList()
categoryName.value = props.editData.category_name
categoryForm.depth = props.editData.depth
categoryForm.parent_id = props.editData.id
if (props.isEdit) {
categoryForm.hierarchy = props.editData.hierarchy
categoryForm.name = props.editData.name
categoryForm.depth = props.editData.depth
categoryForm.category_name = props.editData.category_name
categoryForm.status = props.editData.status
categoryForm.isCourse = props.editData.isCourse
categoryForm.need_pass = props.editData.need_pass
}
})
</script>
<template>
<el-dialog :model-value="dialogVisible" draggable :before-close="handleCancel" title="新增类别" width="60%">
<el-dialog :model-value="dialogVisible" draggable :before-close="handleCancel" :title="props.title" width="60%">
<el-form :model="categoryForm" label-position="right" label-width="auto" :rules="rules" ref="formRef">
<el-form-item label="上级类别:" prop="category">
<el-form-item label="上级类别:" prop="parent_id">
<div @click="handleOpenTree" style="width: 100%">
<el-input v-model="categoryForm.category" disabled>
<el-input v-model="categoryName" disabled>
<template #append>
<el-button :icon="Search" />
</template>
......@@ -80,22 +115,20 @@ onMounted(() => {
</div>
</el-form-item>
<el-form-item label="类别层级:" prop="hierarchy">
<el-input v-model="categoryForm.hierarchy" disabled></el-input>
<el-input v-model="categoryForm.depth" disabled></el-input>
</el-form-item>
<el-form-item label="类别名称:" prop="name">
<el-input v-model="categoryForm.name"></el-input>
<el-form-item label="类别名称:" prop="category_name">
<el-input v-model="categoryForm.category_name"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="categoryForm.status">
<el-radio label="0">正常</el-radio>
<el-radio label="1">停用</el-radio>
<el-radio v-for="(item, id) in statusList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="互动课:" prop="isCourse">
<el-radio-group v-model="categoryForm.isCourse">
<el-radio label="0"></el-radio>
<el-radio label="1"></el-radio>
<el-form-item label="互动课:" prop="need_pass">
<el-radio-group v-model="categoryForm.need_pass">
<el-radio v-for="(item, id) in classList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
......@@ -106,5 +139,7 @@ onMounted(() => {
</span>
</template>
</el-dialog>
<TreeDialog v-model:isTreeVisible="isTreeVisible" @getCheckedLabel="getCheckedLabel" />
<template v-if="isTreeVisible">
<TreeDialog v-model:isTreeVisible="isTreeVisible" @getCheckedLabel="getCheckedLabel" />
</template>
</template>
<script lang="ts" setup>
import { getCategoryList } from '../api'
import type { ElTree } from 'element-plus'
defineProps({
......@@ -9,116 +10,72 @@ defineProps({
})
const emit = defineEmits<{
(e: 'update:isTreeVisible', isTreeVisible: false): void
(e: 'getCheckedLabel', checkedLabel: any): void
(e: 'getCheckedLabel', checkedCategory: any): void
}>()
const handleCancel = () => {
emit('update:isTreeVisible', false)
}
interface Tree {
id: number
label: string
level: number
children?: Tree[]
interface ICategory {
category_name: string
depth: string
id: string
lft: string
need_pass: string
rgt: string
status: string
children?: ICategory[]
}
const filterText = ref('')
let data = ref<ICategory[]>([])
const filterText = ref('') // 搜索字段
const treeRef = ref<InstanceType<typeof ElTree>>()
const defaultProps = {
children: 'children',
label: 'label'
label: 'category_name'
}
const checkedLabel = ref('') // 默认选中项名称
const checkedLevel = ref('') // 默认选中项层级
const checkedCategory = {
checkedId: '',
checkedLabel: '', // 默认选中项名称
checkedLevel: 0 // 默认选中项层级
}
// 监听搜索
watch(filterText, val => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
treeRef.value!.filter(val)
treeRef.value?.filter(val)
})
const filterNode = (value: string, data: Tree) => {
//搜索
const filterNode = (value: string, data: ICategory) => {
console.log(value, 'value', data.category_name, 'data')
if (!value) return true
return data.label.includes(value)
return data.category_name.indexOf(value) != -1
}
// 获取选中节点
const handleNodeClick = (TreeNode: any, node: any, attr: any) => {
console.log(TreeNode, node, attr, '999')
checkedLabel.value = TreeNode.label
checkedLevel.value = TreeNode.level
checkedCategory.checkedLabel = TreeNode.category_name // 类名
checkedCategory.checkedId = TreeNode.id // id
checkedCategory.checkedLevel = parseInt(TreeNode.depth) //层级
}
// 确认
const handleConfirm = () => {
checkedLabel.value && emit('getCheckedLabel', { checkedLabel, checkedLevel })
checkedCategory.checkedLabel && emit('getCheckedLabel', { checkedCategory })
emit('update:isTreeVisible', false)
}
const defaultLabel = 'Level one 1'
const data: Tree[] = [
{
id: 1,
label: 'Level one 1',
level: 1,
children: [
{
id: 4,
label: 'Level two 1-1',
level: 2,
children: [
{
id: 9,
label: 'Level three 1-1-1',
level: 3
},
{
id: 10,
label: 'Level three 1-1-2',
level: 3
}
]
}
]
},
{
id: 2,
label: 'Level one 2',
level: 1,
children: [
{
id: 5,
label: 'Level two 2-1',
level: 2
},
{
id: 6,
label: 'Level two 2-2',
level: 2
}
]
},
{
id: 3,
label: 'Level one 3',
level: 1,
children: [
{
id: 7,
label: 'Level two 3-1',
level: 2
},
{
id: 8,
label: 'Level two 3-2',
level: 2
}
]
}
]
// 获取分类列表
const handleCategoryList = () => {
const params = { type: 'tree' }
getCategoryList(params).then((res: any) => {
data.value = res.data
console.log(data, 'tableData')
})
}
onMounted(() => {
handleCategoryList()
})
</script>
<template>
<el-dialog :model-value="isTreeVisible" draggable :before-close="handleCancel" title="类别选择" width="40%">
......@@ -131,10 +88,10 @@ const data: Tree[] = [
default-expand-all
:expand-on-click-node="false"
:highlight-current="true"
:current-node-key="defaultLabel"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
:filter-node-method="filterNode"
/>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
......
<script setup lang="ts">
import Sortable from 'sortablejs'
// import Sortable from 'sortablejs'
import AddDialog from '../component/AddDialog.vue'
import { Operation } from '@element-plus/icons-vue'
import { getCategoryList, delCategory, createCategory, updateCategory } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false)
const statusMap = { 0: '正常', 1: '停用' }
const form = reactive({
name: ''
const prevCategoryName = ref('') // 上层类别
const title = ref('')
const dialogVisible = ref(false)
let form = reactive({
category_name: ''
})
const search = () => {
// 调接口
console.log('000')
}
const reset = () => {
console.log('111')
}
interface User {
id: number
name: string
hierarchy: number
sort: number
interface ICategory {
category_name: number
depth: string
id: string
lft: string
need_pass: string
rgt: string
status: string
create_time: string
isCourse: string
hasChildren?: boolean
children?: User[]
children?: ICategory[]
}
const tableData: User[] = [
{
id: 1,
name: '紫荆教育',
hierarchy: 1,
sort: 1,
status: '0',
create_time: '2022_11_22',
isCourse: '0',
children: [
{
id: 2,
name: '北京',
hierarchy: 2,
sort: 1,
status: '1',
create_time: '2022_11_22',
isCourse: '0',
children: [
{
id: 3,
name: '朝阳',
hierarchy: 3,
sort: 1,
status: '1',
create_time: '2022_11_22',
isCourse: '0'
},
{
id: 4,
name: '海淀',
hierarchy: 3,
sort: 2,
status: '1',
create_time: '2022_11_22',
isCourse: '1'
}
]
},
{
id: 5,
name: '河南',
hierarchy: 2,
sort: 2,
status: '1',
create_time: '2022_11_22',
isCourse: '1',
children: [
{
id: 6,
name: '信阳',
hierarchy: 3,
sort: 1,
status: '1',
create_time: '2022_11_22',
isCourse: '0'
},
{
id: 7,
name: '南阳',
hierarchy: 3,
sort: 2,
status: '1',
create_time: '2022_11_22',
isCourse: '1'
}
]
}
]
}
]
let tableData = $ref<ICategory[]>([])
const editData = ref({})
const isEdit = ref(false)
const handleEdit = (index: number, row: User) => {
const handleEdit = (index: number, row: ICategory) => {
title.value = '编辑类别'
isEdit.value = true
dialogVisible.value = true
editData.value = row
console.log(index, row)
}
const handleDelete = (index: number, row: User) => {
console.log(index, row)
// 删除分类
const handleDelete = (index: number, row: ICategory) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delCategory(params).then(() => {
ElMessage.success('删除成功')
handleCategoryList()
})
})
}
const dialogVisible = ref(false)
const handleAdd = (index: number, row: User) => {
// 新增类别
const handleAdd = (index: number, row: ICategory) => {
isEdit.value = false
dialogVisible.value = true
console.log(index, row)
title.value = '新增类别'
if (row) {
editData.value = row
if (row.depth === '0') {
prevCategoryName.value = ''
}
} else {
editData.value = tableData[0]
}
}
const confirm = () => {
console.log('0001111')
}
// const sortable = (className: any, targetName: any) => {
// const table = document.querySelector('.' + className + ' .el-table__body-wrapper tbody') as HTMLElement
// console.log(table)
// Sortable.create(table, {
// handle: '.handle',
// // 拖拽完毕后触发
// onEnd(data) {
// const newIndex = data.newIndex as number
// const oldIndex = data.oldIndex as number
// console.log(data, 'data')
// if (newIndex === oldIndex) return
const sortable = (className: any, targetName: any) => {
const table = document.querySelector('.' + className + ' .el-table__body-wrapper tbody') as HTMLElement
console.log(table)
Sortable.create(table, {
handle: '.handle',
// 拖拽完毕后触发
onEnd(data) {
const newIndex = data.newIndex as number
const oldIndex = data.oldIndex as number
console.log(data, 'data')
if (newIndex === oldIndex) return
// targetName.splice(newIndex, 0, targetName.splice(oldIndex, 1))
console.log(targetName, 'pppp')
// // targetName.splice(newIndex, 0, targetName.splice(oldIndex, 1))
// console.log(targetName, 'pppp')
// }
// })
// }
// 获取分类列表
const handleCategoryList = () => {
const params = { type: 'tree' }
getCategoryList(params)
.then((res: any) => {
loading.value = true
tableData = res.data
})
.finally(() => {
loading.value = false
})
}
const handleConfirm = (val: any) => {
console.log(val, 'val')
if (val.isUpdate === 1) {
const params = Object.assign({ id: val.id }, val.categoryForm)
updateCategory(params).then(() => {
ElMessage.success('更新类别成功')
handleCategoryList()
})
} else if (val.isUpdate === 0) {
const params = Object.assign({}, val.categoryForm)
createCategory(params).then(() => {
ElMessage.success('新建类别成功')
handleCategoryList()
})
}
}
// 重置
const handleReset = () => {
form.category_name = ''
handleCategoryList()
}
// 搜索
const handleSearch = () => {
// 调接口
if (form.category_name) {
tableData = rebuildData(form.category_name, tableData)
}
}
// 重点代码 根据name字段模糊匹配树状结构数据,最后将处理好的数据返回出来
const rebuildData = (value: any, arr: any) => {
if (!arr) {
return []
}
let newArr: any = []
arr.forEach((element: any) => {
console.log(element, 'element')
// indexOf用来判读当前节点name字段是否包含所搜索的字符串value
// 返回值:包含则返回索引值,反之返回-1
if (element.category_name.indexOf(value) > -1) {
const ab = rebuildData(value, element.children)
const obj = {
...element,
children: ab
}
newArr.push(obj)
} else {
// 判断当前节点知否有子节点,并且子节点中有数据,有数据继续递归查找
if (element.children && element.children.length > 0) {
const ab = rebuildData(value, element.children)
const obj = {
...element,
children: ab
}
if (ab && ab.length > 0) {
newArr.push(obj)
}
}
}
})
return newArr
}
onMounted(() => {
sortable('t1', tableData) // 参数分别为table的class名称,table的数据data
// sortable('t1', tableData) // 参数分别为table的class名称,table的数据data
handleCategoryList()
})
</script>
<template>
......@@ -152,11 +158,11 @@ onMounted(() => {
<div class="table-list-filter">
<el-form class="filter-form" :model="form">
<el-form-item label="类别名称:" prop="name">
<el-input v-model="form.name"></el-input>
<el-input v-model="form.category_name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="search" class="btn_query">搜索</el-button>
<el-button @click="reset">重置</el-button>
<el-button type="primary" @click="handleSearch" class="btn_query">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</div>
......@@ -169,16 +175,14 @@ onMounted(() => {
ref="dragTable"
:tree-props="{ children: 'children', hasChildren: 'hasChildren', draggable: true }"
highlight-current-row
v-loading="loading"
>
<el-table-column type="index" align="center" class-name="handle">
<el-icon><Operation /></el-icon>
</el-table-column>
<el-table-column prop="name" label="类别名称" align="center" class-name="handle" />
<el-table-column prop="hierarchy" label="层级" align="center" />
<el-table-column prop="status" label="状态" align="center">
<template #default="scope"> {{ statusMap[scope.row.status] }}</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" align="center" />
<el-table-column prop="category_name" label="类别名称" align="center" class-name="handle" />
<el-table-column prop="depth" label="层级" align="center" />
<el-table-column prop="status" label="状态" align="center"> </el-table-column>
<el-table-column align="center" label="操作" width="300px">
<template #default="scope">
<el-button type="primary" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
......@@ -189,7 +193,13 @@ onMounted(() => {
</el-table>
</AppCard>
<template v-if="dialogVisible === true">
<AddDialog v-model:dialogVisible="dialogVisible" @confirm="confirm" :editData="editData" :isEdit="isEdit" />
<AddDialog
v-model:dialogVisible="dialogVisible"
@confirm="handleConfirm"
:editData="editData"
:isEdit="isEdit"
:title="title"
/>
</template>
</template>
<style lang="scss" scoped>
......
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
// 获取讲师列表
export function getTeacherList(params?: { type?: string; page?: number; ['per-page']?: number }) {
return httpRequest.get('/api/resource/v1/backend/lecturer/list', { params })
}
// 删除讲师
export function deleteTeacher(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/lecturer/delete', data)
}
// 更新讲师
export function updateTeacher(data: {
id: string
name: string
avatar: string
status: string
title: string
office: string
education: string
summarize: string
}) {
return httpRequest.post('/api/resource/v1/backend/lecturer/update', data)
}
// 创建讲师
export function createTeacher(data: {
name: string
avatar: string
title: string
status: string
office: string
education: string
summarize: string
}) {
return httpRequest.post('/api/resource/v1/backend/lecturer/create', data)
}
// 获取讲师详情
export function getTeacherDetail(params: { id: string }) {
return httpRequest.get('/api/resource/v1/backend/lecturer/view', { params })
}
<script setup lang="ts">
import { createTeacher } from '../api'
import VEditor from '@tinymce/tinymce-vue'
import AppUpload from '@/components/base/AppUpload.vue'
import { useRouter } from 'vue-router'
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
const router = useRouter()
const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
let ruleForm = reactive({
id: '',
name: '',
position: '',
education: '',
mechanism: '',
desc: '',
imageUrl: ''
status: '1',
name: '', // 姓名
title: '', // 职位
education: '', // 学历
office: '', // 讲师任职机构
avatar: '', // 头像
summarize: '' // 讲师简介
})
const rules = reactive<FormRules>({
name: [
......@@ -25,7 +26,7 @@ const rules = reactive<FormRules>({
trigger: 'blur'
}
],
position: [
title: [
{
required: true,
message: '请输入讲师职位',
......@@ -36,14 +37,13 @@ const rules = reactive<FormRules>({
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
await formEl.validate(valid => {
if (valid) {
console.log('submit!')
router.push('/admin/teacher')
} else {
router.push('/admin/teacher')
console.log('error submit!', fields)
const params = Object.assign({}, ruleForm)
createTeacher(params).then(() => {
ElMessage.success('创建讲师成功')
router.push('/admin/teacher')
})
}
})
}
......@@ -66,8 +66,8 @@ const submitForm = async (formEl: FormInstance | undefined) => {
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="讲师职位:" prop="position">
<el-input v-model="ruleForm.position" />
<el-form-item label="讲师职位:" prop="title">
<el-input v-model="ruleForm.title" />
</el-form-item>
</el-col>
</el-row>
......@@ -78,22 +78,22 @@ const submitForm = async (formEl: FormInstance | undefined) => {
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="讲师任职机构:" prop="mechanism">
<el-input v-model="ruleForm.mechanism" />
<el-form-item label="讲师任职机构:" prop="office">
<el-input v-model="ruleForm.office" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="10">
<el-form-item label="讲师头像:" prop="imageUrl">
<AppUpload v-model="ruleForm.imageUrl" />
<el-form-item label="讲师头像:" prop="avatar">
<AppUpload v-model="ruleForm.avatar" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="讲师简介:" prop="desc">
<v-editor v-model="ruleForm.desc" class="editor" style="width: 1000px"></v-editor>
<el-form-item label="讲师简介:" prop="summarize">
<v-editor v-model="ruleForm.summarize" class="editor" style="width: 1000px"></v-editor>
</el-form-item>
</el-col>
</el-row>
......
<script setup lang="ts">
import { getTeacherDetail, updateTeacher } from '../api'
import { ElMessage } from 'element-plus'
import type { FormRules, FormInstance } from 'element-plus'
import VEditor from '@tinymce/tinymce-vue'
import type { FormRules } from 'element-plus'
import AppUpload from '@/components/base/AppUpload.vue'
const router = useRouter()
const route = useRoute()
const appList = ref()
const id = route.query.id as string
const title = route.query.title as string
const formSize = ref('default')
const isEdit = route.query.isEdit as string
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({
id: '',
name: '',
position: '',
education: '',
mechanism: '',
introduce: '',
picture: '',
desc: ''
title: '', // 职位
education: '', // 学历
office: '', // 讲师任职机构
summarize: '', // 讲师简介
avatar: '', //讲师图片
status: '1'
})
const url = JSON.parse(route.query.form + '').imageUrl as string
const appList = ref()
const rules = reactive<FormRules>({
name: [
{ required: true, message: 'Please input Activity name', trigger: 'blur' },
{ min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' }
],
position: [
{
required: true,
message: 'Please select Activity zone',
trigger: 'change'
}
],
date1: [
{
type: 'date',
required: true,
message: 'Please pick a date',
trigger: 'change'
}
],
date2: [
{
type: 'date',
required: true,
message: 'Please pick a time',
trigger: 'change'
}
],
type: [
{
type: 'array',
required: true,
message: 'Please select at least one activity type',
trigger: 'change'
}
],
resource: [
{
required: true,
message: 'Please select activity resource',
trigger: 'change'
}
]
name: [{ required: true, message: '请输入讲师姓名', trigger: 'blur' }],
title: [{ required: true, message: ' 请输入职位', trigger: 'blur' }]
})
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' }
},
columns: [
{ label: '#', type: 'index', align: 'center' },
{ label: '课程图片', slots: 'table-cover', align: 'center' },
......@@ -78,55 +42,71 @@ const listOptions = {
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '编辑', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 300, align: 'center' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
{ id: 2, title: '视频标题', type: '视频分类' }
]
}
const handleDelete = (row: any) => {
console.log('删除', row)
}
const getUpdateForm = () => {
const editForm = JSON.parse(route.query.form + '')
Object.keys(ruleForm).forEach(key => {
ruleForm[key] = editForm[key]
const getTeacherInfo = () => {
getTeacherDetail({ id: id }).then(res => {
console.log(res.data)
Object.keys(ruleForm).forEach(key => {
ruleForm[key] = res.data[key]
})
})
}
// 更新讲师
const handleUpdate = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
const params = Object.assign({}, ruleForm)
updateTeacher(params).then(() => {
ElMessage.success('创建讲师成功')
router.push('/admin/teacher')
})
}
})
}
onMounted(() => {
// 更新获取讲师信息
getUpdateForm()
getTeacherInfo()
})
</script>
<template>
<AppCard :title="title">
<el-form :model="ruleForm" :size="formSize" :rules="rules" label-position="right" label-width="100px">
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-position="right" label-width="100px">
<el-row>
<el-col :span="4">
<el-form-item label="讲师图片:" prop="picture">
<el-image style="width: 300px" :src="url" />
<el-col :span="8">
<el-form-item label="讲师图片:" prop="avatar">
<div v-if="isEdit === '1'">暂无照片</div>
<AppUpload v-model="ruleForm.avatar" v-else />
</el-form-item>
</el-col>
<el-col :span="8" style="margin-left: 80px">
<el-form-item label="讲师姓名:" prop="name">
<el-input v-model="ruleForm.name" />
<el-input v-model="ruleForm.name" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师职位:" prop="position">
<el-input v-model="ruleForm.position" />
<el-form-item label="讲师职位:" prop="title">
<el-input v-model="ruleForm.title" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师学历:" prop="education">
<el-input v-model="ruleForm.education" />
<el-input v-model="ruleForm.education" :disabled="isEdit === '1'" />
</el-form-item>
<el-form-item label="讲师任职机构:" prop="mechanism">
<el-input v-model="ruleForm.mechanism" />
<el-form-item label="讲师任职机构:" prop="office">
<el-input v-model="ruleForm.office" :disabled="isEdit === '1'" />
</el-form-item>
</el-col>
<el-form-item>
<el-button type="primary" v-if="isEdit !== '1'" @click="handleUpdate(ruleFormRef)">保存</el-button>
</el-form-item>
</el-row>
<el-form-item label="讲师简介:" prop="introduce">
<v-editor v-model="ruleForm.introduce" style="width: 70%"></v-editor>
<el-form-item label="讲师简介:" prop="summarize">
<v-editor v-model="ruleForm.summarize" style="width: 70%" :disabled="isEdit === '1'"></v-editor>
</el-form-item>
</el-form>
<el-card>
......
<script setup lang="ts">
// import { getVideoList } from '../api'
import { ElMessage,ElMessageBox } from 'element-plus'
import { getTeacherList, deleteTeacher } from '../api'
const router = useRouter()
const appList = ref()
const listOptions = {
remote: {
// httpRequest: getVideoList,
httpRequest: getTeacherList,
params: { type: '' }
},
filters: [
{ type: 'input', prop: 'type', label: '讲师姓名:' },
{ type: 'input', prop: 'project_id', label: '讲师任职机构:' },
{ type: 'input', prop: 'category_id', label: '讲师职位:' },
{ type: 'input', prop: 'category_id', label: '讲师学历:' }
{ type: 'input', prop: 'name', label: '讲师姓名:' },
{ type: 'input', prop: 'office', label: '讲师任职机构:' },
{ type: 'input', prop: 'title', label: '讲师职位:' },
{ type: 'input', prop: 'education', label: '讲师学历:' }
],
columns: [
{ label: '#', type: 'index', align: 'center' },
{ label: '讲师头像', slots: 'table-img', align: 'center' },
{ label: '讲师姓名', prop: 'name', align: 'center' },
{ label: '讲师任职机构', prop: 'mechanism', align: 'center' },
{ label: '讲师职位', prop: 'position', align: 'center' },
{ label: '讲师任职机构', prop: 'office', align: 'center' },
{ label: '讲师职位', prop: 'title', align: 'center' },
{ label: '讲师学历', prop: 'education', align: 'center' },
{ label: '编辑', prop: 'edit', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
],
data: [
{
id: 1,
imageUrl: 'https://img0.baidu.com/it/u=1872881124,390027250&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=333',
name: '章三',
mechanism: '紫荆',
position: '讲师',
education: '本科',
edit: '123',
created_time: '2022-05-30'
}
]
}
// 删除讲师
const handleDelete = (row: any) => {
console.log('删除', row)
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
deleteTeacher({ id: row.id }).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 更新讲师
const handleUpdate = (row: any) => {
console.log(row)
router.push({
path: '/admin/teacher/detail',
query: {
form: JSON.stringify(row),
id: row.id,
isEdit: '0',
title: '更新讲师'
}
})
}
//讲师详情
const handleDetail = (row: any) => {
console.log(row.id)
router.push({
path: '/admin/teacher/detail',
query: {
id: row.id,
isEdit: '1',
title: '讲师详情'
}
})
}
</script>
<template>
......@@ -60,13 +66,11 @@ const handleUpdate = (row: any) => {
<el-button type="primary" round>添加讲师</el-button>
</router-link>
<template #header-aside> </template>
<template #table-img="{ row }"> <img :src="row.imageUrl" alt="" style="width: 100%" /></template>
<template #table-img="{ row }"> <img :src="row.avatar" alt="" style="width: 100%" /></template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="{ path: '/admin/teacher/detail', query: { title: '讲师详情', form: JSON.stringify(row) } }">
<el-button type="primary" plain>查看</el-button>
</router-link>
<el-button type="primary" plain @click="handleDetail(row)">查看</el-button>
<el-button type="primary" plain @click="handleUpdate(row)">更新</el-button>
<el-button type="primary" plain @click="handleDelete(row)">删除</el-button>
</el-space>
......
......@@ -2,5 +2,5 @@ import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
return httpRequest.get('/api/resource/backend/video/index', { params })
}
......@@ -2,20 +2,20 @@ import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
return httpRequest.get('/api/resource/backend/video/index', { params })
}
// 创建视频
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/create', data)
return httpRequest.post('/api/resource/backend/video/create', data)
}
// 更新视频
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data)
return httpRequest.post('/api/resource/backend/video/update', data)
}
// 获取视频详情
export function getVideo(params: { id: string }) {
return httpRequest.get('/api/psp/backend/video/view', { params })
return httpRequest.get('/api/resource/backend/video/view', { params })
}
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
// 获取封面列表
export function getCoverList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/resource/v1/backend/cover/list', { params })
}
// 创建封面
export function createCover(data?: { title?: string; status?: number; type?: number; url?: number }) {
return httpRequest.post('/api/resource/v1/backend/cover/create', data)
}
// 更新封面
export function updateCover(data?: { title?: string; status?: number; type?: number; url?: number }) {
return httpRequest.post('/api/resource/v1/backend/cover/update', data)
}
// 删除封面
export function deleteCover(data: { id: any }) {
return httpRequest.post('/api/resource/v1/backend/cover/delete', data)
}
// 获取公共字典列表
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
}
<script lang="ts" setup>
// import { getMapList } from '../api'
import AppUpload from '@/components/base/AppUpload.vue'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
interface mapList {
label: string
value: string
data_dictionary_id: string
sort: string
remark: string
id: string
}
// 封面类型
let typeList = $ref<mapList[]>([])
// 封面状态
let statusList = $ref<mapList[]>([])
const form = reactive({
status: '0',
imageUrl: '',
type: '0'
title: '',
status: '1',
url: '',
type: '1'
})
const rules = {
const rules = reactive<FormRules>({
status: [{ required: true, message: '请选择状态', trigger: 'blur' }],
imageUrl: [{ required: true, message: '请上传图片', trigger: 'change' }],
url: [{ required: true, message: '请上传图片', trigger: 'change' }],
type: [{ required: true, message: '请选择封面类型', trigger: 'blur' }]
}
})
const props = defineProps({
isShowDialog: {
type: Boolean,
......@@ -27,10 +44,11 @@ const props = defineProps({
})
interface Emits {
(e: 'update:isShowDialog', isShowDialog: boolean): void
(e: 'confirm'): void
(e: 'createCover', form: any): void
}
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
// 普通属性
......@@ -40,32 +58,47 @@ const handleCancel = () => {
// 确定
const handleConfirm = () => {
emit('update:isShowDialog', false)
emit('confirm')
if (props.isEdit === true) {
emit('createCover', { form, isUpdate: 1, id: props.editData.id })
} else {
form.title = form.url
emit('createCover', { form, isUpdate: 0 })
}
}
const getMapList = async () => {
await store.getMapList()
typeList = store.mapList.filter((item: any) => item.key === 'system_cover_type')[0].values
statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
}
const change = () => {
console.log(form, statusList)
}
onMounted(() => {
if (props.isEdit) {
form.status = props.editData.status
form.imageUrl = props.editData.cover_img
form.url = props.editData.url
form.type = props.editData.type
form.title = props.editData.url
}
getMapList()
})
</script>
<template>
<el-dialog :model-value="isShowDialog" draggable :before-close="handleCancel" width="30%">
<el-form :model="form" :rules="rules">
<el-form :model="form" :rules="rules" ref="ruleFormRef">
<el-form-item label="封面类型:" prop="type">
<el-select v-model="form.type">
<el-option label="课程" value="0"></el-option>
<el-option label="视频" value="1"></el-option>
<el-option v-for="(item, id) in typeList" :key="id" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图片地址:" prop="imageUrl">
<AppUpload v-model="form.imageUrl" />
<el-form-item label="图片地址:" prop="url">
<AppUpload v-model="form.url" />
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio label="0">成功</el-radio>
<el-radio label="1">失败</el-radio>
<el-radio-group v-model="form.status" @change="change()">
<el-radio v-for="(item, id) in statusList" :key="id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
......
<script setup lang="ts">
import { getCoverList, createCover, updateCover, deleteCover } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
import AddDialog from '../component/AddDialog.vue'
const appList = ref()
const isShowDialog = ref(false)
const isEdit = ref(false)
const editData = ref({})
const listOptions = {
remote: {
// httpRequest: getVideoList,
httpRequest: getCoverList,
params: { type: '' }
},
columns: [
{ label: '封面地址', prop: 'cover_url', align: 'center' },
{ label: '封面预览', prop: 'cover_img', slots: 'table-cover', align: 'center' },
{ label: '封面类型', prop: 'type', align: 'center' },
{ label: '封面地址', prop: 'url', align: 'center' },
{ label: '封面预览', prop: 'url', slots: 'table-cover', align: 'center' },
{ label: '封面类型', prop: 'type_name', align: 'center' },
{
label: '状态',
prop: 'status',
align: 'center',
computed(row: any) {
console.log(row)
if (row.row.status === '0') {
return '正常'
} else if (row.row.status === '1') {
return '停用'
} else {
return '-'
}
}
prop: 'status_name',
align: 'center'
},
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
],
data: [
{
id: 1,
cover_url: 'https://img0.baidu.com/it/u=1106810636,3829865668&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=505',
cover_img: 'https://img0.baidu.com/it/u=1106810636,3829865668&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=505',
type: '视频',
status: '0',
created_time: '2022-06-01'
}
]
}
// 删除
const handleDelete = (row: any) => {
console.log('删除', row)
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params: any = { id: row.id }
deleteCover(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 确定
const handleConfirm = () => {
console.log('123')
const handleConfirm = (val: any) => {
if (val.isUpdate === 1) {
// 更新封面
const params = Object.assign({ id: val.id }, val.form)
updateCover(params).then(() => {
appList.value.refetch()
})
} else {
// 添加封面
const params = Object.assign({}, val.form)
createCover(params).then(() => {
appList.value.refetch()
})
}
}
// 添加
const handleAdd = () => {
......@@ -70,7 +71,7 @@ const handleEdit = (row: any) => {
<AppList v-bind="listOptions" ref="appList">
<template #header-aside> </template>
<template #table-cover="{ row }">
<img :src="row.cover_img" alt="" style="width: 100px" />
<img :src="row.url" alt="" style="width: 100px" />
</template>
<template #table-operate="{ row }">
<el-space>
......@@ -79,7 +80,12 @@ const handleEdit = (row: any) => {
</el-space>
</template>
<template v-if="isShowDialog === true">
<AddDialog v-model:isShowDialog="isShowDialog" @confirm="handleConfirm" :editData="editData" :isEdit="isEdit" />
<AddDialog
v-model:isShowDialog="isShowDialog"
@createCover="handleConfirm"
:editData="editData"
:isEdit="isEdit"
/>
</template>
</AppList>
</AppCard>
......
......@@ -2,5 +2,75 @@ import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
return httpRequest.get('/api/resource/backend/video/index', { params })
}
// 获取字典列表
export function getDictionaryList(params?: {
name?: string
key?: number
status?: boolean
created_time_start?: string
created_time_end?: string
page?: number
page_size?: number
}) {
return httpRequest.get('/api/resource/v1/backend/data-dictionary/list', { params })
}
// 新增字典
export function createDictionary(data: {
name: string
key: number
status: boolean
remark: string
can_edit: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/create', data)
}
// 更新字典
export function updateDictionary(data: {
id: string
name: string
key: number
status: boolean
remark: string
can_edit: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/update', data)
}
// 删除字典
export function delDictionary(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/delete', data)
}
// 获取字典的值的列表
export function getDictionaryItemList(params?: { data_dictionary_id: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/resource/v1/backend/data-dictionary/value-list', { params })
}
// 新增字典的值
export function createDictionaryItem(data: {
data_dictionary_id: string
label: number
value: boolean
sort: string
remark: string
can_edit: string
status: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-create', data)
}
// 新增字典的值
export function updateDictionaryItem(data: {
id: string
data_dictionary_id: string
label: number
value: boolean
sort: string
remark: string
can_edit: string
status: string
}) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-update', data)
}
// 删除字典的值
export function delDictionaryItem(data: { id: string }) {
return httpRequest.post('/api/resource/v1/backend/data-dictionary/value-delete', data)
}
\ No newline at end of file
<script lang="ts" setup>
import type { IMapList } from '../types'
import { useMapStore } from '@/stores/map'
import type { FormInstance, FormRules } from 'element-plus'
const store = useMapStore()
const ruleFormRef = ref<FormInstance>()
const form = reactive({
name: '',
type: '',
status: '0',
remark: ''
key: '',
status: '1',
remark: '',
})
const rules = {
let statusList = $ref<IMapList[]>([])
const rules = reactive<FormRules>({
name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
type: [{ required: true, message: '请输入字典类型', trigger: 'blur' }]
}
key: [{ required: true, message: '请输入字典类型', trigger: 'blur' }]
})
const props = defineProps({
isShowDialog: {
type: Boolean,
......@@ -25,7 +34,7 @@ const props = defineProps({
})
interface Emits {
(e: 'update:isShowDialog', isShowDialog: boolean): void
(e: 'confirm'): void
(e: 'confirm', form: object): void
}
const emit = defineEmits<Emits>()
......@@ -36,19 +45,35 @@ const handleCancel = () => {
emit('update:isShowDialog', false)
}
// 确定
const handleConfirm = () => {
emit('update:isShowDialog', false)
emit('confirm')
const handleConfirm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
if (props.isEdit === true) {
emit('update:isShowDialog', false)
emit('confirm', { form, isUpdate: 1, id: props.rowInfo.id })
} else {
emit('update:isShowDialog', false)
emit('confirm', { form, isUpdate: 0 })
}
}
})
}
const getMapList = async () => {
await store.getMapList()
statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
console.log(statusList, 'statusList')
}
onMounted(() => {
getMapList()
console.log(props.rowInfo, 'props.rowInfo')
if (props.isEdit) {
form.name = props.rowInfo.name
form.type = props.rowInfo.type
if (props.rowInfo.status === '正常') {
form.status = '0'
} else {
form.key = props.rowInfo.key
if (props.rowInfo.status === '有效') {
form.status = '1'
} else {
form.status = '0'
}
form.remark = props.rowInfo.remark
}
......@@ -61,18 +86,17 @@ onMounted(() => {
:before-close="handleCancel"
:title="isEdit === true ? '编辑字典' : '新增字典'"
>
<el-form :model="form" ref="formRef" :rules="rules" label-width="120px">
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典名称:" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="字典类型:" prop="type">
<el-input v-model="form.type"></el-input>
<el-form-item label="字典类型:" prop="key">
<el-input v-model="form.key"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio label="0">正常</el-radio>
<el-radio label="1">停用</el-radio>
<el-radio v-for="(item, index) in statusList" :key="index" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
......@@ -81,7 +105,7 @@ onMounted(() => {
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm">确定</el-button>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
......
<script lang="ts" setup>
import type { IMapList } from '../types'
import { useMapStore } from '@/stores/map'
import type { FormInstance, FormRules } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const store = useMapStore()
let statusList = $ref<IMapList[]>([])
const form = reactive({
tag: '',
label: '',
value: '',
key: '',
type: '',
status: '0',
remark: ''
status: '1',
remark: '',
sort: ''
})
const rules = reactive<FormRules>({
label: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
value: [{ required: true, message: '请输入字典键值', trigger: 'blur' }],
sort: [{ required: true, message: '请输入字典排序', trigger: 'blur' }]
})
const rules = {
tag: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
key: [{ required: true, message: '请输入字典键值', trigger: 'blur' }],
sort: [{ required: true, message: '请输入字典键值', trigger: 'blur' }]
}
const props = defineProps({
isListAddDialog: {
type: Boolean,
......@@ -27,7 +38,7 @@ const props = defineProps({
})
interface Emits {
(e: 'update:isListAddDialog', isListAddDialog: boolean): void
(e: 'confirm'): void
(e: 'confirm', form: object): void
}
const emit = defineEmits<Emits>()
......@@ -38,37 +49,55 @@ const handleCancel = () => {
emit('update:isListAddDialog', false)
}
// 确定
const handleConfirm = () => {
emit('update:isListAddDialog', false)
emit('confirm')
const handleConfirm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(valid => {
if (valid) {
if (props.isEdit === true) {
emit('update:isListAddDialog', false)
emit('confirm', { form, isUpdate: 1, id: props.editData.id })
} else {
emit('update:isListAddDialog', false)
emit('confirm', { form, isUpdate: 0 })
}
}
})
}
const getMapList = async () => {
await store.getMapList()
statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
console.log(statusList, 'statusList')
}
onMounted(() => {
console.log('props.editData.status', props.editData.status)
getMapList()
if (props.isEdit) {
form.tag = props.editData.tag
form.key = props.editData.key
form.label = props.editData.label
form.value = props.editData.value
form.type = props.editData.type
form.remark = props.editData.remark
form.status = props.editData.status
form.sort = props.editData.sort
}
})
</script>
<template>
<el-dialog :model-value="isListAddDialog" draggable :before-close="handleCancel">
<el-form :model="form" :rules="rules" label-width="120px">
<el-form-item label="字典标签:" prop="tag">
<el-input v-model="form.tag"></el-input>
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典标签:" prop="label">
<el-input v-model="form.label"></el-input>
</el-form-item>
<el-form-item label="字典键值:" prop="value">
<el-input v-model="form.value"></el-input>
</el-form-item>
<el-form-item label="字典键值:" prop="key">
<el-input v-model="form.key"></el-input>
<el-form-item label="字典排序:" prop="sort">
<el-input v-model="form.sort"></el-input>
</el-form-item>
<el-form-item label="字典类型:" prop="type">
<el-input v-model="form.type"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio label="0">正常</el-radio>
<el-radio label="1">停用</el-radio>
<el-radio v-for="(item, index) in statusList" :key="index" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
......@@ -77,7 +106,7 @@ onMounted(() => {
</el-form>
<template #footer>
<span>
<el-button type="primary" @click="handleConfirm">确定</el-button>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
......
export interface IMapList {
label: string
value: string
data_dictionary_id: string
sort: string
remark: string
id: string
}
<script setup lang="ts">
import type { IMapList } from '../types'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { getDictionaryList, createDictionary, updateDictionary, delDictionary } from '../api'
import AddDialog from '../component/AddDialog.vue'
const store = useMapStore()
const router = useRouter()
const appList = ref()
const isShowDialog = ref(false) // 新增字典弹框状态
const isEdit = ref(false) //是否可编辑
const rowInfo = ref({})
// 状态
let statusList = $ref<IMapList[]>([])
//表单每行数据
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '', created_time: '' }
httpRequest: getDictionaryList,
params: {
type: '',
created_time_start: '',
created_time_end: ''
}
},
filters: [
{ type: 'input', prop: 'name', label: '字典名称:' },
{ type: 'input', prop: 'type', label: '字典类型:' },
{ type: 'input', prop: 'key', label: '字典类型:' },
{
type: 'select',
prop: 'status',
label: '字典状态:',
options: [
{ label: '正常', value: '0' },
{ label: '停用', value: '1' }
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
},
{ type: 'input', prop: 'created_time', slots: 'created_time', label: '创建时间:' }
{
type: 'input',
label: '创建时间:',
slots: 'created_time_start',
prop: 'created_time_start'
},
{ slots: 'created_time_end', prop: 'created_time_end' }
],
columns: [
{ label: '字典主键', slots: 'key', width: 224, align: 'center' },
{ label: '字典主键', prop: 'id', width: 224, align: 'center' },
{ label: '字典名称', prop: 'name', align: 'center' },
{ label: '字典类型', prop: 'type', align: 'center' },
{ label: '字典类型', prop: 'key', align: 'center' },
{
label: '状态',
prop: 'status',
align: 'center',
computed(row: any) {
if (row.status === '0') {
return '正常'
} else {
return '停用'
}
}
prop: 'status_name',
align: 'center'
},
{ label: '备注 ', prop: 'remark', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
......@@ -61,31 +71,63 @@ const listOptions = {
}
]
}
// 新增弹窗
const handleAdd = () => {
console.log('新增字典')
isShowDialog.value = true
isEdit.value = false
}
// 编辑弹窗
const handleEdit = (row: any) => {
console.log('编辑字典', row)
rowInfo.value = row
isShowDialog.value = true
isEdit.value = true
console.log(rowInfo)
}
//删除
const handleDelete = (row: any) => {
console.log('删除字典', row)
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delDictionary(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
// 跳转列表
const handleList = (row: any) => {
console.log('列表', row.rowList)
router.push({
path: '/system/dictionary/rowList',
query: {
rowList: JSON.stringify(row.rowList)
id: row.id
}
})
// listShowDialog.value = true
}
const getMapList = async () => {
await store.getMapList()
statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
console.log(statusList, 'statusList')
}
// 确定
const handleConfirm = (val: any) => {
if (val.isUpdate === 1) {
// 更新字典
const params = Object.assign({ id: val.id }, val.form)
updateDictionary(params).then(() => {
ElMessage.success('更新成功')
appList.value.refetch()
})
} else {
// 新增字典
const params = Object.assign({}, val.form)
createDictionary(params).then(() => {
ElMessage.success('新增成功')
appList.value.refetch()
})
}
}
onMounted(() => {
getMapList()
})
</script>
<template>
......@@ -94,17 +136,12 @@ const handleList = (row: any) => {
<el-row>
<el-button type="primary" @click="handleAdd">新增字典</el-button>
</el-row>
<template v-slot:created_time="{ params }">
<el-date-picker
v-model="params.created_time"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
size="small"
>
</el-date-picker>
<template v-slot:created_time_start="{ params }">
<el-date-picker v-model="params.created_time_start" type="date" placeholder="开始时间"> </el-date-picker>
<p class="separator">&nbsp;&nbsp;&nbsp;&nbsp;-</p>
</template>
<template v-slot:created_time_end="{ params }">
<el-date-picker v-model="params.created_time_end" type="date" placeholder="结束时间"> </el-date-picker>
</template>
<template #table-operate="{ row }">
<el-space>
......@@ -114,8 +151,15 @@ const handleList = (row: any) => {
</el-space>
</template>
<template v-if="isShowDialog === true">
<AddDialog v-model:isShowDialog="isShowDialog" :isEdit="isEdit" :rowInfo="rowInfo" />
<AddDialog
v-model:isShowDialog="isShowDialog"
:isEdit="isEdit"
:rowInfo="rowInfo"
:statusList="statusList"
@confirm="handleConfirm"
/>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import { getDictionaryItemList, createDictionaryItem, updateDictionaryItem, delDictionaryItem } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
import ListAddDialog from '../component/ListAddDialog.vue'
const route = useRoute()
const appList = ref()
......@@ -7,38 +10,27 @@ const isEdit = ref(false)
const isListAddDialog = ref(false)
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' }
httpRequest: getDictionaryItemList,
params: { data_dictionary_id: route.query.id }
},
columns: [
{ label: '字典编码', prop: 'code', align: 'center' },
{ label: '字典标签', prop: 'tag', align: 'center' },
{ label: '字典键值', prop: 'key', align: 'center' },
{ label: '字典编码', prop: 'data_dictionary_id', align: 'center' },
{ label: '字典标签', prop: 'label', align: 'center' },
{ label: '字典键值', prop: 'value', align: 'center' },
{
label: '状态',
prop: 'status',
align: 'center',
computed(row: any) {
console.log(row.row)
if (row.row.status === '0') {
return '正常'
} else if (row.row.status === '1') {
return '停用'
} else {
return '-'
}
}
prop: 'status_name',
align: 'center'
},
{ label: '备注 ', prop: 'remark', align: 'center' },
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center', minWidth: 180 }
],
data: JSON.parse(route.query.rowList + '')
]
}
const handleAdd = () => {
isListAddDialog.value = true
isEdit.value = true
isEdit.value = false
editData.value = {}
console.log('新增字典')
}
......@@ -49,10 +41,32 @@ const handleEdit = (row: any) => {
console.log('编辑字典', row)
}
const handleDelete = (row: any) => {
console.log('删除字典', row)
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
const params = { id: row.id }
delDictionaryItem(params).then(() => {
ElMessage.success('删除成功')
appList.value.refetch()
})
})
}
const confirm = () => {
console.log('0001111')
// 确定
const handleConfirm = (val: any) => {
console.log(val.id, '9999')
if (val.isUpdate === 1) {
// 更新字典的值
const params = Object.assign({ id: val.id, data_dictionary_id: route.query.id }, val.form)
updateDictionaryItem(params).then(() => {
ElMessage.success('更新成功')
appList.value.refetch()
})
} else {
// 新增字典的值
const params = Object.assign({ data_dictionary_id: route.query.id }, val.form)
createDictionaryItem(params).then(() => {
ElMessage.success('新增成功')
appList.value.refetch()
})
}
}
</script>
......@@ -71,6 +85,11 @@ const confirm = () => {
</AppList>
</AppCard>
<template v-if="isListAddDialog === true">
<ListAddDialog v-model:isListAddDialog="isListAddDialog" @confirm="confirm" :editData="editData" :isEdit="isEdit" />
<ListAddDialog
v-model:isListAddDialog="isListAddDialog"
@confirm="handleConfirm"
:editData="editData"
:isEdit="isEdit"
/>
</template>
</template>
import { defineStore } from 'pinia'
import { getMapList } from '@/api/base'
interface IMapState {
id: string
key: string
name: string
remark: string
values: IValuesList[]
}
interface IValuesList {
data_dictionary_id: string
id: string
label: string
remark: string
sort: string
value: string
}
export const useMapStore = defineStore({
id: 'map',
state: () => {
return {
mapList: [] as IMapState | any
}
},
getters: {},
actions: {
async getMapList() {
const res = await getMapList()
this.mapList = res.data
}
}
})
......@@ -29,6 +29,7 @@ export const useUserStore = defineStore({
async getUser() {
const res = await getUser()
this.user = res.data
console.log(res.data, 'res.data')
},
async logout() {
await logout()
......
......@@ -26,6 +26,12 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
},
proxy: {
'/api/resource': {
// target: 'http://localhost-activity-frontend.ezijing.com',
target: 'http://localhost-resource-backend.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/resource/, '')
},
'/api': 'https://learn-api.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论