Commit f17ace8d authored by Jstar Xu's avatar Jstar Xu

feat: 城市管理页面ui初始化

parent b8f87e2a
<script setup lang="ts"> <script setup lang="ts">
import { useDesignSettingStore } from '@/store/modules/design-setting' import { useDesignSettingStore } from '@/store/modules/design-setting'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import { readonly } from 'vue' import { readonly, computed } from 'vue'
import { useRouter } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { ExpandRight, ExpandLeft } from '@icon-park/vue-next' import { ExpandRight, ExpandLeft } from '@icon-park/vue-next'
const defaultAvatar = 'https://mkp-dev.oss-cn-shenzhen.aliyuncs.com/game-template/20221018/1666079174947.png' const defaultAvatar = 'https://mkp-dev.oss-cn-shenzhen.aliyuncs.com/game-template/20221018/1666079174947.png'
...@@ -10,7 +10,7 @@ const defaultAvatar = 'https://mkp-dev.oss-cn-shenzhen.aliyuncs.com/game-templat ...@@ -10,7 +10,7 @@ const defaultAvatar = 'https://mkp-dev.oss-cn-shenzhen.aliyuncs.com/game-templat
const designSettingStore = useDesignSettingStore() const designSettingStore = useDesignSettingStore()
const userStore = useUserStore() const userStore = useUserStore()
const router = useRouter() const router = useRouter()
// const currentRoute = useRoute() const route = useRoute()
const menuOptions = readonly([ const menuOptions = readonly([
{ {
...@@ -35,7 +35,13 @@ function onDropdownSelect(key: number) { ...@@ -35,7 +35,13 @@ function onDropdownSelect(key: number) {
}) })
} }
} }
const breadcrumbs = computed(() => {
const matchedRoutes = route.matched.filter((item) => item.meta && item.meta.title)
return matchedRoutes.map((item) => ({
path: item.path,
title: item.meta.title,
}))
})
// function handleRefreshPage() { // function handleRefreshPage() {
// router.replace({ path: currentRoute.fullPath }) // router.replace({ path: currentRoute.fullPath })
// } // }
...@@ -64,6 +70,11 @@ function onDropdownSelect(key: number) { ...@@ -64,6 +70,11 @@ function onDropdownSelect(key: number) {
:stroke-width="3" :stroke-width="3"
@click="handleSidebarDisplayStatusChange('collapse')" @click="handleSidebarDisplayStatusChange('collapse')"
/> />
<el-breadcrumb class="ml-3">
<el-breadcrumb-item v-for="(breadcrumb, index) in breadcrumbs" :key="index" :to="{ path: breadcrumb.path }">
<el-text>{{ breadcrumb.title }}</el-text>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
</div> </div>
<div class="mr-5 flex sm:mr-6"> <div class="mr-5 flex sm:mr-6">
......
import { type RouteRecordRaw } from 'vue-router'
import Layout from '@/layout/index.vue'
export default [
{
path: '/city-management',
meta: {
rank: 1001,
title: '城市管理',
icon: 'icon-city',
},
component: Layout,
children: [
{
path: '',
name: 'CityManagement',
meta: {
rank: 1001,
title: '列表',
hideSideMenItem: true,
},
component: () => import('@/views/city-management/city-management.vue'),
},
],
},
] as RouteRecordRaw[]
import { reactive, ref } from 'vue'
type Actions = 'edit' | 'create' | 'view' | 'del'
const ACTIONSCN = {
view: '查看',
edit: '编辑',
create: '新增',
del: '删除',
}
export function useForm(initFormData = {}) {
const formRef = ref<any>(null)
const formModel = ref({ ...initFormData })
// const rules = {
// required: {
// required: true,
// message: '此为必填项',
// trigger: ['blur', 'change'],
// },
// }
const validation = async () => {
return formRef.value.validate()
}
return [formRef, formModel, validation] as const
}
export function useModal() {
const options = reactive({
visible: false,
title: '',
callback: () => {},
loading: false,
})
return options
}
export function useTableCrud({
name,
actions: { create, read, update, del },
initForm,
}: {
name: string
actions: {
read?: (params: any) => any
create?: (params: any) => any
update?: (params: any) => any
del?: (params: any) => any
}
initForm?: any
}) {
const modalAction = ref('')
const modelOptions = useModal()
const [modalFormRef, modalForm, validation] = useForm(initForm)
/** 新增 */
function handleAdd(row: any = {}) {
handleOpen({ action: 'create', row: Object.assign({}, { ...initForm }, { ...row }) })
}
/** 修改 */
function handleEdit(row: any) {
handleOpen({ action: 'edit', row })
}
/** 查看 */
function handleView(row: any) {
handleOpen({ action: 'view', row })
}
/** 打开modal */
function handleOpen(options = {} as { title?: string; action: Actions; row?: any; onOk?: () => Promise<any> }) {
const { action, row, onOk, title } = options
modalAction.value = action
modalForm.value = { ...row }
// console.log(modalRef.value)
modelOptions.visible = true
modelOptions.title = title || ACTIONSCN[action] + name
modelOptions.callback = async () => {
if (typeof onOk === 'function') {
return await onOk()
} else {
return await handleSave(action)
}
}
}
/** 保存 */
async function handleSave(action: Actions) {
if (!action && !['edit', 'add'].includes(modalAction.value)) {
return false
}
await validation()
const actions = {
create: {
api: () => create?.(modalForm.value),
cb: () => ElMessage.success('新增成功'),
},
edit: {
api: () => update?.(modalForm.value),
cb: () => ElMessage.success('保存成功'),
},
}
const currentAction = actions[modalAction.value as keyof typeof actions]
try {
modelOptions.loading = true
const data = await currentAction.api()
currentAction.cb()
modelOptions.loading = false
if (data && read) read(data)
} catch (error) {
console.error(error)
modelOptions.loading = false
return false
}
}
/** 删除 */
function handleDelete(id: string | number, confirmOptions = {}) {
if (!id && id !== 0) return
ElMessageBox.confirm('确定删除?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
beforeClose: async (action, instance, done) => {
if (action === 'confirm') {
try {
instance.confirmButtonLoading = true
const data = await del?.(id)
ElMessage.success('删除成功')
instance.confirmButtonLoading = false
read?.(data)
} catch (error) {
console.error(error)
instance.confirmButtonLoading = false
}
done()
} else {
done()
}
},
...confirmOptions,
})
}
return {
modal: modelOptions,
modalFormRef,
modalAction,
modalForm,
validation,
handleAdd,
handleDelete,
handleEdit,
handleView,
handleOpen,
handleSave,
}
}
<script setup lang="ts">
import { Search } from '@icon-park/vue-next'
import { ref, useTemplateRef, watchEffect } from 'vue'
import GeneralTableLayout from '@/components/general-table-layout.vue'
import CityEditDialog from './components/city-edit-dialog.vue'
import { useTableCrud } from '@/utils/hook/useTableCrud'
const searchKeyword = ref('')
const paginationConfig = ref({
currentPage: 1,
pageSize: 10,
total: 40,
})
const curdDialogRef = useTemplateRef('curdDialogRef')
const tableData = ref([
{
id: 1,
title: '广州',
status: '状态',
short: 'GZ',
remark: '备注信息',
date: '2016-05-03',
},
])
watchEffect(() => {
if (curdDialogRef.value) {
modalFormRef.value = curdDialogRef.value.formRef
}
})
const { modal, modalFormRef, modalForm, handleAdd, handleDelete, handleEdit } = useTableCrud({
name: '城市',
actions: {
create: (e) => {
console.log(e)
// modal.visible = false
},
read: (e) => {
console.log(e)
},
update: (e) => {
console.log(e)
},
del: (e) => {
console.log(e)
},
},
initForm: {
status: true,
},
})
</script>
<template>
<GeneralTableLayout v-model:pagination-config="paginationConfig">
<template #header>
<div>
<el-input v-model="searchKeyword" style="width: 240px" placeholder="请输入想要搜索的内容">
<template #suffix>
<Search theme="outline" size="16" fill="#333" :stroke-width="3" />
</template>
</el-input>
</div>
<div class="ml-[20px]">
<el-button type="primary" plain>查询</el-button>
<el-button type="danger" plain>重置</el-button>
</div>
<div class="ml-auto">
<el-button type="primary" @click="handleAdd()">新增</el-button>
</div>
</template>
<el-table :data="tableData" row-key="id" border class="w-full">
<el-table-column type="index" width="50" />
<el-table-column prop="short" label="首字母" width="80" />
<el-table-column prop="title" label="城市名" width="230" />
<el-table-column prop="status" label="状态" width="180">
<template #default="{ row }">
<el-switch v-model="row.status"></el-switch>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" text bg @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" text bg @click="handleDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</GeneralTableLayout>
<CityEditDialog
ref="curdDialogRef"
v-model:dialog-visible="modal.visible"
v-model:form-data="modalForm"
:modal-options="{ title: modal.title, callback: modal.callback, loading: modal.loading }"
/>
</template>
<script setup lang="ts">
import { useTemplateRef, reactive } from 'vue'
import type { FormRules } from 'element-plus'
interface Props {
modalOptions: {
title: string
callback: () => void
loading: boolean
}
}
defineProps<Props>()
const dialogVisible = defineModel<boolean>('dialogVisible', { default: false })
const formData = defineModel<any>('formData', { default: {} })
const formRef = useTemplateRef('formRef')
const rules = reactive<FormRules<{ title: string; short: string; status: string; remark: string }>>({
title: [{ required: true, message: '请输入城市名称', trigger: 'blur' }],
short: [{ required: true, message: '请输入城市名称缩写', trigger: 'blur' }],
// status: [{ message: '请选择状态', trigger: 'blur' }],
// remark: [{ message: '请输入备注信息', trigger: 'blur' }],
})
defineExpose({ formRef })
</script>
<template>
<el-dialog
v-model="dialogVisible"
:title="modalOptions.title"
width="670"
@close="
() => {
formRef?.resetFields()
}
"
>
<el-form ref="formRef" status-icon :model="formData" :rules="rules" label-width="120px" style="width: 70%">
<el-form-item label="城市名称" prop="title">
<el-input v-model="formData.title" />
</el-form-item>
<el-form-item label="城市名称缩写" prop="short">
<el-input v-model="formData.short" />
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="formData.status" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" :autosize="{ minRows: 3 }" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<el-button
:loading="modalOptions.loading"
type="primary"
@click="
() => {
// console.log( modalOptions.callback)
modalOptions.callback()
}
"
>提交</el-button
>
</template>
</el-dialog>
</template>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment