|
|
@@ -1,80 +1,265 @@
|
|
|
<script lang="ts" setup>
|
|
|
import {
|
|
|
WebtopoProjectApi,
|
|
|
+ type WebtopoProjectCreateReqVO,
|
|
|
type WebtopoProjectPageReqVO,
|
|
|
+ type WebtopoProjectUpdateReqVO,
|
|
|
type WebtopoProjectVO
|
|
|
} from '@/api/pms/maotu'
|
|
|
+import { IotDeviceApi } from '@/api/pms/device'
|
|
|
+import { useUserStore } from '@/store/modules/user'
|
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
|
-import { ElMessage } from 'element-plus'
|
|
|
+import dayjs from 'dayjs'
|
|
|
+import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
|
|
|
|
|
defineOptions({ name: 'MaotuList' })
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
+const id = useUserStore().getUser.deptId
|
|
|
+const deptId = id
|
|
|
+
|
|
|
const loading = ref(false)
|
|
|
-const initialized = ref(false)
|
|
|
const list = ref<WebtopoProjectVO[]>([])
|
|
|
const total = ref(0)
|
|
|
-const queryParams = reactive<WebtopoProjectPageReqVO>({
|
|
|
+
|
|
|
+const initQuery: WebtopoProjectPageReqVO = {
|
|
|
pageNo: 1,
|
|
|
- pageSize: 10,
|
|
|
+ pageSize: 12,
|
|
|
+ deptId: id,
|
|
|
projectName: ''
|
|
|
+}
|
|
|
+
|
|
|
+const query = ref<WebtopoProjectPageReqVO>({ ...initQuery })
|
|
|
+
|
|
|
+type FormMode = 'create' | 'config'
|
|
|
+type ProjectForm = Partial<WebtopoProjectUpdateReqVO>
|
|
|
+
|
|
|
+interface DeviceOption {
|
|
|
+ label: string
|
|
|
+ value: number
|
|
|
+}
|
|
|
+
|
|
|
+const createVisible = ref(false)
|
|
|
+const createLoading = ref(false)
|
|
|
+const deviceLoading = ref(false)
|
|
|
+const formRef = ref<FormInstance>()
|
|
|
+const formMode = ref<FormMode>('create')
|
|
|
+const deviceOptions = ref<DeviceOption[]>([])
|
|
|
+const createForm = ref<ProjectForm>({
|
|
|
+ projectName: '',
|
|
|
+ linkedDevices: [],
|
|
|
+ remark: ''
|
|
|
})
|
|
|
|
|
|
+const rules: FormRules = {
|
|
|
+ projectName: [{ required: true, message: '请输入项目名称', trigger: ['blur', 'change'] }]
|
|
|
+}
|
|
|
+
|
|
|
const loadList = useDebounceFn(async () => {
|
|
|
loading.value = true
|
|
|
try {
|
|
|
- const data = await WebtopoProjectApi.getWebtopoProjectPage(queryParams)
|
|
|
- list.value = data.list || []
|
|
|
- total.value = data.total || 0
|
|
|
+ const data = await WebtopoProjectApi.getWebtopoProjectPage(query.value)
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ list.value = data
|
|
|
+ total.value = data.length
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ list.value = data?.list || []
|
|
|
+ total.value = data?.total || 0
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
- initialized.value = true
|
|
|
}
|
|
|
}, 200)
|
|
|
|
|
|
-const handleQuery = () => {
|
|
|
- queryParams.pageNo = 1
|
|
|
+function getChineseName(value?: string) {
|
|
|
+ return (value || '').split('~~')[0]
|
|
|
+}
|
|
|
+
|
|
|
+function formatDeviceLabel(item: any) {
|
|
|
+ const code = item.deviceCode || ''
|
|
|
+ const name = getChineseName(item.deviceName || item.label)
|
|
|
+ return [code, name].filter(Boolean).join(' - ')
|
|
|
+}
|
|
|
+
|
|
|
+async function loadDeviceOptions(deptId?: number) {
|
|
|
+ if (!deptId) {
|
|
|
+ deviceOptions.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ deviceLoading.value = true
|
|
|
+ try {
|
|
|
+ const data = await IotDeviceApi.simpleDevices({ deptId })
|
|
|
+ deviceOptions.value = (Array.isArray(data) ? data : []).map((item: any) => ({
|
|
|
+ label: formatDeviceLabel(item),
|
|
|
+ value: item.id
|
|
|
+ }))
|
|
|
+ } finally {
|
|
|
+ deviceLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function handleSizeChange(val: number) {
|
|
|
+ query.value.pageSize = val
|
|
|
+ handleQuery()
|
|
|
+}
|
|
|
+
|
|
|
+function handleCurrentChange(val: number) {
|
|
|
+ query.value.pageNo = val
|
|
|
loadList()
|
|
|
}
|
|
|
|
|
|
-const resetQuery = () => {
|
|
|
- queryParams.projectName = ''
|
|
|
+function handleQuery(setPage = true) {
|
|
|
+ if (setPage) {
|
|
|
+ query.value.pageNo = 1
|
|
|
+ }
|
|
|
+ loadList()
|
|
|
+}
|
|
|
+
|
|
|
+function resetQuery() {
|
|
|
+ query.value = { ...initQuery }
|
|
|
handleQuery()
|
|
|
}
|
|
|
|
|
|
-const handleEdit = (row: WebtopoProjectVO) => {
|
|
|
+async function openCreate() {
|
|
|
+ formMode.value = 'create'
|
|
|
+ createForm.value = {
|
|
|
+ id: undefined,
|
|
|
+ projectName: '',
|
|
|
+ linkedDevices: [],
|
|
|
+ remark: ''
|
|
|
+ }
|
|
|
+ deviceOptions.value = []
|
|
|
+ createVisible.value = true
|
|
|
+ await loadDeviceOptions(deptId)
|
|
|
+ await nextTick()
|
|
|
+ formRef.value?.clearValidate()
|
|
|
+}
|
|
|
+
|
|
|
+async function openConfig(row: WebtopoProjectVO) {
|
|
|
+ formMode.value = 'config'
|
|
|
+ createForm.value = {
|
|
|
+ id: row.id,
|
|
|
+ projectName: row.projectName,
|
|
|
+ linkedDevices: row.linkedDevices || [],
|
|
|
+ remark: row.remark
|
|
|
+ }
|
|
|
+ createVisible.value = true
|
|
|
+ await loadDeviceOptions(deptId)
|
|
|
+ await nextTick()
|
|
|
+ formRef.value?.clearValidate()
|
|
|
+}
|
|
|
+
|
|
|
+function handleCreateClose() {
|
|
|
+ createVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+async function submitCreate() {
|
|
|
+ if (!formRef.value) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ createLoading.value = true
|
|
|
+ await formRef.value.validate()
|
|
|
+ const data: WebtopoProjectCreateReqVO = {
|
|
|
+ projectName: createForm.value.projectName!,
|
|
|
+ linkedDevices: createForm.value.linkedDevices || [],
|
|
|
+ remark: createForm.value.remark
|
|
|
+ }
|
|
|
+ const res = await WebtopoProjectApi.createWebtopoProject(data)
|
|
|
+ const projectId = typeof res === 'number' ? res : res?.data
|
|
|
+
|
|
|
+ if (!projectId) {
|
|
|
+ ElMessage.error('新增成功,但未返回项目 ID')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success('新增成功')
|
|
|
+ handleCreateClose()
|
|
|
+ router.push(`/maotu/edit/${projectId}`)
|
|
|
+ } finally {
|
|
|
+ createLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function submitConfig() {
|
|
|
+ if (!formRef.value || !createForm.value.id) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ createLoading.value = true
|
|
|
+ await formRef.value.validate()
|
|
|
+ const data = { ...createForm.value } as WebtopoProjectUpdateReqVO
|
|
|
+ await WebtopoProjectApi.updateWebtopoProject(data)
|
|
|
+ ElMessage.success('更新成功')
|
|
|
+ handleCreateClose()
|
|
|
+ loadList()
|
|
|
+ } finally {
|
|
|
+ createLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function submitForm() {
|
|
|
+ if (formMode.value === 'config') {
|
|
|
+ submitConfig()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ submitCreate()
|
|
|
+}
|
|
|
+
|
|
|
+function formatCreateTime(value?: number | string) {
|
|
|
+ if (!value) return '-'
|
|
|
+ const time = typeof value === 'number' && value.toString().length === 10 ? value * 1000 : value
|
|
|
+ return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
|
|
|
+}
|
|
|
+
|
|
|
+function getLinkedDeviceCount(row: WebtopoProjectVO) {
|
|
|
+ return row.linkedDevices?.length || 0
|
|
|
+}
|
|
|
+
|
|
|
+function handleEdit(row: WebtopoProjectVO) {
|
|
|
router.push(`/maotu/edit/${row.id}`)
|
|
|
}
|
|
|
|
|
|
-const handlePreview = (row: WebtopoProjectVO) => {
|
|
|
+function handlePreview(row: WebtopoProjectVO) {
|
|
|
router.push(`/maotu/preview/${row.id}`)
|
|
|
}
|
|
|
|
|
|
-const handleConfig = (row: WebtopoProjectVO) => {
|
|
|
- ElMessage.info(`配置功能待接入:${row.projectName}`)
|
|
|
+function handleConfig(row: WebtopoProjectVO) {
|
|
|
+ openConfig(row)
|
|
|
}
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- loadList()
|
|
|
-})
|
|
|
+watch(
|
|
|
+ [() => query.value.deptId, () => query.value.projectName],
|
|
|
+ () => {
|
|
|
+ handleQuery()
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+)
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
<div
|
|
|
- class="grid grid-rows-[48px_1fr] gap-y-3 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
|
|
|
+ class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
|
|
|
+ <DeptTreeSelect
|
|
|
+ :top-id="156"
|
|
|
+ :deptId="deptId"
|
|
|
+ v-model="query.deptId"
|
|
|
+ :show-title="false"
|
|
|
+ class="row-span-2" />
|
|
|
+
|
|
|
<el-form
|
|
|
size="default"
|
|
|
- :model="queryParams"
|
|
|
- class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-6 gap-8 flex items-center justify-between">
|
|
|
+ class="filter-form bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between">
|
|
|
<div class="flex items-center gap-8">
|
|
|
<el-form-item label="组态名称">
|
|
|
<el-input
|
|
|
- v-model="queryParams.projectName"
|
|
|
+ v-model="query.projectName"
|
|
|
clearable
|
|
|
- class="!w-180px"
|
|
|
+ class="!w-240px"
|
|
|
placeholder="请输入组态名称"
|
|
|
- @keyup.enter="handleQuery" />
|
|
|
+ @keyup.enter="handleQuery()" />
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
<el-form-item>
|
|
|
@@ -82,86 +267,186 @@ onMounted(() => {
|
|
|
<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="openCreate">
|
|
|
+ <Icon icon="ep:plus" class="mr-5px" /> 新建
|
|
|
+ </el-button>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
- <div
|
|
|
- class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow p-3 overflow-hidden flex flex-col min-h-0">
|
|
|
- <div
|
|
|
- v-loading="loading"
|
|
|
- class="flex-1 min-h-0 border border-gray-100 dark:border-gray-700 rounded-lg overflow-hidden">
|
|
|
- <div
|
|
|
- v-if="initialized && !loading && !list.length"
|
|
|
- class="h-full flex items-center justify-center">
|
|
|
- <el-empty description="暂无组态项目" :image-size="100" />
|
|
|
- </div>
|
|
|
- <div
|
|
|
- v-else
|
|
|
- class="h-full overflow-y-auto p-3 grid grid-cols-[repeat(auto-fill,minmax(260px,1fr))] auto-rows-max content-start gap-3">
|
|
|
- <div
|
|
|
- v-for="item in list"
|
|
|
- :key="item.id"
|
|
|
- class="group bg-white dark:bg-[#1d1e1f] rounded-lg shadow-sm hover:shadow-md border border-gray-100 dark:border-gray-700 overflow-hidden transition-all duration-300">
|
|
|
- <div class="h-150px bg-[var(--el-fill-color-light)]">
|
|
|
- <el-image
|
|
|
- v-if="item.thumbnail"
|
|
|
- :src="item.thumbnail"
|
|
|
- fit="cover"
|
|
|
- class="w-full h-full"
|
|
|
- lazy>
|
|
|
- <template #error>
|
|
|
- <div
|
|
|
- class="h-full flex items-center justify-center text-12px text-[var(--el-text-color-secondary)]">
|
|
|
- 缩略图加载失败
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </el-image>
|
|
|
+ <div class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow flex flex-col min-h-0">
|
|
|
+ <div class="flex-1 relative">
|
|
|
+ <el-auto-resizer class="absolute">
|
|
|
+ <template #default="{ height }">
|
|
|
+ <el-scrollbar v-loading="loading" :height="height" view-class="p-4 min-h-full">
|
|
|
<div
|
|
|
- v-else
|
|
|
- class="h-full flex items-center justify-center text-12px text-[var(--el-text-color-secondary)]">
|
|
|
- 暂无缩略图
|
|
|
+ v-if="!loading && !list.length"
|
|
|
+ class="h-full min-h-[360px] flex flex-col items-center justify-center text-gray-400">
|
|
|
+ <div class="i-lucide-inbox text-5xl mb-4 op-50"></div>
|
|
|
+ <p class="text-sm font-medium">暂无组态项目</p>
|
|
|
+ <p class="text-xs mt-1 op-60">尝试调整组织或搜索条件</p>
|
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
|
- <div class="p-3">
|
|
|
<div
|
|
|
- class="text-15px font-600 text-gray-800 dark:text-gray-100 truncate"
|
|
|
- :title="item.projectName">
|
|
|
- {{ item.projectName }}
|
|
|
- </div>
|
|
|
- <div
|
|
|
- class="mt-2 h-36px text-12px leading-18px text-gray-400 dark:text-gray-500 line-clamp-2">
|
|
|
- {{ item.remark || '暂无备注' }}
|
|
|
- </div>
|
|
|
- <div class="mt-3 flex items-center justify-end gap-2">
|
|
|
- <el-button size="small" type="primary" link @click="handleEdit(item)">
|
|
|
- <Icon icon="ep:edit" class="mr-4px" /> 编辑
|
|
|
- </el-button>
|
|
|
- <el-button size="small" type="primary" link @click="handlePreview(item)">
|
|
|
- <Icon icon="ep:view" class="mr-4px" /> 预览
|
|
|
- </el-button>
|
|
|
- <el-button size="small" type="primary" link @click="handleConfig(item)">
|
|
|
- <Icon icon="ep:setting" class="mr-4px" /> 配置
|
|
|
- </el-button>
|
|
|
+ v-else
|
|
|
+ class="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] auto-rows-max content-start gap-4">
|
|
|
+ <div
|
|
|
+ v-for="item in list"
|
|
|
+ :key="item.id"
|
|
|
+ class="group bg-white dark:bg-[#262727] rounded-lg shadow-sm border border-gray-100 dark:border-gray-700 hover:shadow-[0_10px_24px_rgba(15,23,42,0.12)] hover:-translate-y-1 transition-all duration-300 overflow-hidden">
|
|
|
+ <div class="relative h-170px bg-[var(--el-fill-color-light)] overflow-hidden">
|
|
|
+ <el-image
|
|
|
+ v-if="item.thumbnail"
|
|
|
+ :src="item.thumbnail"
|
|
|
+ fit="cover"
|
|
|
+ class="w-full h-full transition-transform duration-500 group-hover:scale-105"
|
|
|
+ lazy>
|
|
|
+ <template #error>
|
|
|
+ <div
|
|
|
+ class="h-full flex flex-col items-center justify-center text-12px text-[var(--el-text-color-secondary)]">
|
|
|
+ <Icon icon="ep:picture" class="text-28px mb-2 op-60" />
|
|
|
+ 缩略图加载失败
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-image>
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ class="h-full flex flex-col items-center justify-center text-12px text-[var(--el-text-color-secondary)] bg-gradient-to-br from-gray-50 to-gray-100 dark:from-[#252728] dark:to-[#1d1e1f]">
|
|
|
+ <Icon icon="ep:picture" class="text-32px mb-2 op-60" />
|
|
|
+ 暂无缩略图
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="absolute left-3 top-3 flex items-center gap-1.5 rounded-full bg-black/45 backdrop-blur px-2.5 py-1 text-xs text-white">
|
|
|
+ <Icon icon="ep:cpu" />
|
|
|
+ {{ getLinkedDeviceCount(item) }} 台设备
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="p-4">
|
|
|
+ <div class="flex items-start justify-between gap-3">
|
|
|
+ <el-tooltip effect="dark" :content="item.projectName" placement="top-start">
|
|
|
+ <div
|
|
|
+ class="text-16px font-600 text-gray-800 dark:text-gray-100 truncate"
|
|
|
+ :title="item.projectName">
|
|
|
+ {{ item.projectName || '-' }}
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
+ <!-- <el-tag size="small" effect="light" type="info" class="shrink-0">
|
|
|
+ ID {{ item.id }}
|
|
|
+ </el-tag> -->
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="mt-3 grid gap-2 text-12px text-gray-500 dark:text-gray-400">
|
|
|
+ <div class="flex items-center justify-between gap-3">
|
|
|
+ <span class="flex items-center gap-1.5 text-gray-400">
|
|
|
+ <Icon icon="ep:clock" /> 创建时间
|
|
|
+ </span>
|
|
|
+ <span class="font-medium text-gray-600 dark:text-gray-300">
|
|
|
+ {{ formatCreateTime(item.createTime) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="mt-3 text-12px leading-20px text-gray-400 dark:text-gray-500 line-clamp-2"
|
|
|
+ :title="item.remark">
|
|
|
+ {{ item.remark || '暂无备注' }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="px-4 py-3 bg-gray-50/80 dark:bg-[#1d1e1f] flex items-center justify-end gap-3 group-hover:bg-blue-50/40 dark:group-hover:bg-blue-900/10 transition-colors">
|
|
|
+ <el-button size="small" type="primary" link @click="handleEdit(item)">
|
|
|
+ <Icon icon="ep:edit" class="mr-4px" /> 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="primary" link @click="handlePreview(item)">
|
|
|
+ <Icon icon="ep:view" class="mr-4px" /> 预览
|
|
|
+ </el-button>
|
|
|
+ <el-button size="small" type="primary" link @click="handleConfig(item)">
|
|
|
+ <Icon icon="ep:setting" class="mr-4px" /> 配置
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </template>
|
|
|
+ </el-auto-resizer>
|
|
|
</div>
|
|
|
|
|
|
- <div class="pt-3 flex justify-end shrink-0">
|
|
|
- <Pagination
|
|
|
- v-model:limit="queryParams.pageSize"
|
|
|
- v-model:page="queryParams.pageNo"
|
|
|
+ <div class="h-10 mt-4 mb-4 px-4 flex items-center justify-end shrink-0">
|
|
|
+ <el-pagination
|
|
|
+ size="default"
|
|
|
+ v-show="total > 0"
|
|
|
+ v-model:current-page="query.pageNo"
|
|
|
+ v-model:page-size="query.pageSize"
|
|
|
+ :background="true"
|
|
|
+ :page-sizes="[12, 20, 30, 50, 100]"
|
|
|
:total="total"
|
|
|
- @pagination="loadList" />
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="createVisible"
|
|
|
+ :title="formMode === 'config' ? '配置关联设备' : '新建组态项目'"
|
|
|
+ width="560px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ destroy-on-close>
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="createForm"
|
|
|
+ :rules="rules"
|
|
|
+ label-position="top"
|
|
|
+ require-asterisk-position="right"
|
|
|
+ size="default">
|
|
|
+ <el-form-item label="项目名称" prop="projectName">
|
|
|
+ <el-input v-model="createForm.projectName" clearable placeholder="请输入项目名称" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="绑定设备" prop="linkedDevices">
|
|
|
+ <el-select
|
|
|
+ v-model="createForm.linkedDevices"
|
|
|
+ multiple
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ :loading="deviceLoading"
|
|
|
+ class="w-full"
|
|
|
+ placeholder="请选择绑定设备">
|
|
|
+ <el-option
|
|
|
+ v-for="item in deviceOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="备注" prop="remark">
|
|
|
+ <el-input
|
|
|
+ v-model="createForm.remark"
|
|
|
+ type="textarea"
|
|
|
+ :autosize="{ minRows: 3, maxRows: 6 }"
|
|
|
+ show-word-limit
|
|
|
+ :maxlength="500"
|
|
|
+ resize="none"
|
|
|
+ placeholder="请输入备注" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="handleCreateClose">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="createLoading" @click="submitForm">保存</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
|
-:deep(.el-form-item) {
|
|
|
+.filter-form :deep(.el-form-item) {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
|