增加行政执法管理等部分前端页面

This commit is contained in:
Zhangchaoyang02 2025-02-21 11:36:40 +08:00
parent 68f9b6d965
commit 27ff842418
6 changed files with 1872 additions and 0 deletions

View File

@ -0,0 +1,594 @@
<template>
<browser
:component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
:default-query-params="queryParams"
@update:query-params="queryParams = $event"
@update:actions="actions = $event"
@update:dialog-config="dialogConfig = $event"
>
<!-- 查询面板 -->
<template #queryPanel="{ queryParams: qp }">
<el-form ref="queryForm" :model="qp" label-width="100px">
<el-row class="query-condition">
<el-col :span="6">
<el-form-item label="机构名称" prop="agencyName">
<el-input v-model="qp.agencyName" placeholder="请输入机构名称" clearable />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="机构代码" prop="agencyCode">
<el-input v-model="qp.agencyCode" placeholder="请输入机构代码" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<!-- 自定义内容区域左侧树形结构 + 右侧列表 -->
<template #table="{ permissions: perms, data, selection, mergeActions, queryParams: qp }">
<div class="agency-content">
<!-- 左侧树形结构 -->
<div class="agency-tree">
<div class="tree-header">
<span class="tree-title">机构树</span>
<el-button
type="primary"
size="small"
@click="refreshTree"
:icon="Refresh"
circle
/>
</div>
<el-tree
ref="treeRef"
v-loading="treeLoading"
:data="treeData"
:props="treeProps"
:highlight-current="true"
:expand-on-click-node="false"
node-key="agencyId"
lazy
:load="loadTreeNode"
@node-click="handleNodeClick"
>
<template #default="{ node, data: nodeData }">
<span class="custom-tree-node">
<span class="node-label">{{ node.label }}</span>
<span class="node-code">{{ nodeData.agencyCode }}</span>
</span>
</template>
</el-tree>
</div>
<!-- 右侧列表 -->
<div class="agency-list">
<BusinessTable
ref="busiTable"
v-loading="tableConfig.tableLoading"
:data-res="data"
:config="tableConfig"
:query-params="qp"
:permissions="perms"
@do-query="mergeActions.query"
@show-modify="mergeActions.modify"
@show-detail="mergeActions.detail"
@do-remove="mergeActions.remove"
@table-selection="mergeActions.handleSelectionChange"
@do-customize="mergeActions.doCustomize"
@query-params="mergeActions.updateQueryParams"
>
<el-table-column prop="agencyName" label="机构名称" min-width="200" show-overflow-tooltip />
<el-table-column prop="agencyCode" label="机构代码" min-width="150" />
<el-table-column prop="agencySimpleCode" label="机构简码" min-width="120" />
<el-table-column prop="agencyLevel" label="机构级别" min-width="100" align="center" />
<el-table-column prop="orderNum" label="排序号" min-width="100" align="center" />
</BusinessTable>
</div>
</div>
</template>
<!-- 对话框内容 -->
<template #dialogContent="{ dialogConfig: dc }">
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="机构名称" prop="agencyName">
<el-input
:disabled="dc.mode === 'detail'"
v-model="dc.data.agencyName"
placeholder="请输入机构名称"
maxlength="255"
show-word-limit
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="机构代码" prop="agencyCode">
<el-input
:disabled="dc.mode === 'detail'"
v-model="dc.data.agencyCode"
placeholder="请输入机构代码"
maxlength="17"
show-word-limit
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="机构简码" prop="agencySimpleCode">
<el-input
disabled
v-model="dc.data.agencySimpleCode"
placeholder="自动生成"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="上级机构" prop="parent">
<AgencySelector
v-model="dc.data.parent"
:disabled="dc.mode === 'detail'"
placeholder="请选择上级机构(不选则为根节点)"
:lazy-load="true"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序号" prop="orderNum">
<el-input-number
:disabled="dc.mode === 'detail'"
v-model="dc.data.orderNum"
:min="0"
controls-position="right"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12" v-if="dc.mode === 'detail'">
<el-form-item label="机构级别" prop="agencyLevel">
<el-input :disabled="true" v-model="dc.data.agencyLevel" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="dc.mode === 'detail'">
<el-form-item label="是否叶子节点" prop="leaf">
<el-tag :type="dc.data.leaf ? 'success' : 'info'" size="small">
{{ dc.data.leaf ? '是' : '否' }}
</el-tag>
</el-form-item>
</el-col>
<el-col :span="12" v-if="dc.mode === 'detail'">
<el-form-item label="机构路径" prop="agencyPath">
<el-input :disabled="true" v-model="dc.data.agencyPath" />
</el-form-item>
</el-col>
</el-row>
</template>
</browser>
</template>
<script setup>
import { reactive, toRefs, ref, onMounted, nextTick, watch } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import Browser from '@/components/Browser.vue'
import BusinessTable from '@/components/BusinessTable.vue'
import AgencySelector from '@/components/AgencySelector.vue'
import { ElMessage } from 'element-plus'
import agencies from '@/api/lawenforcement/Agency.js'
//
const treeRef = ref(null)
const busiTable = ref(null)
//
const state = reactive({
componentLoading: false,
treeLoading: false,
treeData: [], //
currentNode: null, //
permissions: {
query: true,
add: true,
modify: true,
detail: true,
delete: true,
deleteAll: true,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false,
canDeleteCustom: (row) => {
//
return row.leaf === true
},
canModifyCustom: () => {
return true
}
},
tableConfig: {
hasControlColumn: true,
controlWidth: '180',
tableLoading: false,
selectable: (row) => {
//
return row.leaf === true
}
},
apiConfig: {
api: agencies,
modelId: 'agencyId',
},
dialogConfig: {
type: 'min',
show: false,
mode: 'detail',
formLabelWidth: '120px',
baseTitle: '执法机构',
loading: false,
rules: {
agencyName: [
{ required: true, message: '机构名称不能为空', trigger: 'blur' },
{ min: 1, max: 255, message: '机构名称长度为1-255个字符', trigger: 'blur' }
],
agencyCode: [
{ required: true, message: '机构代码不能为空', trigger: 'blur' },
{ min: 1, max: 17, message: '机构代码长度为1-17个字符', trigger: 'blur' }
],
agencySimpleCode: [
{ min: 0, max: 17, message: '机构简码长度不能超过17个字符', trigger: 'blur' }
],
orderNum: [
{ type: 'number', message: '排序号必须为数字', trigger: 'blur' }
]
},
data: {},
actions: {}
},
actions: {
add: handleAdd,
startQuery: handleStartQuery
},
queryParams: {
parentId: null //
},
treeProps: {
label: 'agencyName',
children: 'children',
value: 'agencyId',
isLeaf: 'leaf'
}
})
const {
componentLoading,
treeLoading,
treeData,
currentNode,
permissions,
tableConfig,
apiConfig,
dialogConfig,
actions,
queryParams,
treeProps
} = toRefs(state)
/**
* 生成机构简码从左到右每两位一组保留非"00"分组去掉末尾连续为0的分组
* 例如610113000000 -> 610113去掉末尾3个"00"
* 例如01610198017000000 -> 016101980170去掉末尾3个"00"
*/
function generateSimpleCode(agencyCode) {
if (!agencyCode) return ''
const code = String(agencyCode)
const groups = []
// 1
for (let i = 0; i < code.length; i += 2) {
groups.push(code.slice(i, i + 2))
}
// 0'00' '0'
while (groups.length > 0) {
const last = groups[groups.length - 1]
if (last === '00' || last === '0') {
groups.pop()
} else {
break
}
}
return groups.join('')
}
//
onMounted(() => {
// 使lazyload
//
nextTick(() => {
setTimeout(() => {
if (treeRef.value) {
const rootNodes = treeRef.value.store.root.childNodes
rootNodes.forEach(node => {
node.expand()
})
}
}, 500)
})
//
watch(
() => dialogConfig.value.data.agencyCode,
(newCode) => {
if (newCode) {
dialogConfig.value.data.agencySimpleCode = generateSimpleCode(newCode)
}
}
)
})
/**
* 懒加载树节点的子节点
* @param {Object} node - 当前节点
* @param {Function} resolve - 回调函数传入子节点数据
*/
async function loadTreeNode(node, resolve) {
//
if (node.level === 0) {
try {
const res = await agencies.querylist({ parentId: '0' })
if (res.success) {
resolve(res.data || [])
} else {
ElMessage.error(res.message || '加载机构失败')
resolve([])
}
} catch (error) {
console.error('加载机构失败:', error)
ElMessage.error('加载机构失败')
resolve([])
}
} else {
//
try {
const res = await agencies.querylist({ parentId: node.data.agencyId })
if (res.success) {
resolve(res.data || [])
} else {
ElMessage.error(res.message || '加载子机构失败')
resolve([])
}
} catch (error) {
console.error('加载子机构失败:', error)
ElMessage.error('加载子机构失败')
resolve([])
}
}
}
/**
* 刷新树形数据
* 懒加载模式下需要重置树的store状态
*/
function refreshTree() {
const tree = treeRef.value
if (tree) {
treeLoading.value = true
//
tree.setCurrentKey(null)
currentNode.value = null
//
const rootNodes = tree.store.root.childNodes
rootNodes.forEach(node => {
tree.store.root.removeChild(node)
})
//
loadTreeNode(tree.store.root, (data) => {
data.forEach(nodeData => {
tree.store.root.insertChild({ data: nodeData })
})
treeLoading.value = false
//
nextTick(() => {
setTimeout(() => {
const newRootNodes = tree.store.root.childNodes
newRootNodes.forEach(node => {
node.expand()
})
}, 100)
})
})
//
queryParams.value.parentId = null
nextTick(() => {
if (busiTable.value && busiTable.value.resetQuery) {
busiTable.value.resetQuery()
}
})
}
}
/**
* 处理初始查询
* 由于使用了自定义table插槽需要确保busiTable已挂载
*/
function handleStartQuery() {
nextTick(() => {
if (busiTable.value && busiTable.value.resetQuery) {
busiTable.value.resetQuery()
}
const parentId = queryParams.value?.parentId
if (actions.value && actions.value.query && parentId !== null && parentId !== undefined && parentId !== '') {
actions.value.query()
}
})
}
/**
* 树节点点击事件
* @param {Object} data - 节点数据
*/
function handleNodeClick(data) {
currentNode.value = data
// ID
queryParams.value.parentId = data.agencyId
// 使nextTickqueryParams
nextTick(() => {
if (busiTable.value && busiTable.value.resetQuery) {
busiTable.value.resetQuery()
//
if (actions.value && actions.value.query) {
actions.value.query()
}
}
})
}
/**
* 新增机构处理
*/
async function handleAdd() {
dialogConfig.value.mode = 'add'
dialogConfig.value.title = '新增执法机构'
//
// parentnull
const parent = currentNode.value ? currentNode.value : null
//
let orderNum = 0
try {
const parentId = parent ? parent.agencyId : '0'
const res = await agencies.getNextOrderNum(parentId)
if (res.success && res.data !== null && res.data !== undefined) {
orderNum = res.data
}
} catch (error) {
console.error('获取排序号失败:', error)
orderNum = 0
}
dialogConfig.value.data = {
agencyId: null,
agencyName: '',
agencyCode: '',
agencySimpleCode: '',
agencyLevel: null,
leaf: true,
orderNum: orderNum,
agencyPath: '',
parent: parent,
children: []
}
dialogConfig.value.show = true
}
</script>
<style lang="scss" scoped>
.agency-content {
display: flex;
height: 100%;
gap: 8px;
padding-top: 8px;
overflow: hidden;
flex: 1;
.agency-tree {
width: 300px;
min-width: 300px;
max-width: 300px;
background: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
overflow: hidden;
.tree-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #e8e8e8;
flex-shrink: 0;
.tree-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
}
:deep(.el-tree) {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
}
.custom-tree-node {
display: flex;
flex-direction: column;
flex: 1;
padding: 4px 0;
.node-label {
font-size: 14px;
color: #333;
margin-bottom: 2px;
}
.node-code {
font-size: 12px;
color: #999;
}
}
:deep(.el-tree-node__content) {
height: auto;
min-height: 40px;
padding: 4px 0;
}
:deep(.el-tree-node__label) {
flex: 1;
}
}
.agency-list {
flex: 1;
min-width: 0;
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
:deep(.business-table) {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin-top: 0;
}
}
}
//
@media (max-width: 1200px) {
.agency-content {
.agency-tree {
width: 250px;
min-width: 250px;
max-width: 250px;
}
}
}
</style>

View File

@ -0,0 +1,271 @@
<template>
<browser
:component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
:default-query-params="queryParams"
@update:query-params="queryParams = $event"
@update:actions="actions = $event"
@update:dialog-config="dialogConfig = $event"
>
<template #queryPanel="{ queryParams: qp }">
<el-form :model="qp" label-width="100px">
<el-row class="query-condition">
<el-col :span="6">
<el-form-item label="姓名" prop="officerName">
<el-input v-model="qp.officerName" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="执法号" prop="lawNo">
<el-input v-model="qp.lawNo" placeholder="请输入执法号" clearable />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="qp.contactPhone" placeholder="请输入联系电话" clearable />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="系统用户ID" prop="certificateNo">
<el-input v-model="qp.certificateNo" placeholder="请输入系统用户ID" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<el-table-column prop="officerName" label="姓名" min-width="140" show-overflow-tooltip />
<el-table-column prop="lawNo" label="执法号" min-width="140" />
<el-table-column prop="contactPhone" label="联系电话" min-width="140" />
<el-table-column prop="agencyName" label="机构名称" min-width="180" />
<el-table-column prop="certificateNo" label="系统用户ID" min-width="160" />
<template #dialogContent="{ dialogConfig: dc }">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="officerName">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.officerName" placeholder="请输入姓名" maxlength="100" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="执法号" prop="lawNo">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.lawNo" placeholder="请输入执法号" maxlength="50" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="contactPhone">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.contactPhone" placeholder="请输入联系电话" maxlength="20" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="系统用户ID" prop="certificateNo">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.certificateNo" placeholder="请输入系统用户ID" maxlength="50" show-word-limit />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="所属机构" prop="agency">
<AgencySelector v-model="dc.data.agency" :disabled="dc.mode === 'detail'" placeholder="请选择机构" :lazy-load="true" />
</el-form-item>
</el-col>
</el-row>
</template>
</browser>
</template>
<script setup>
import { reactive, toRefs, ref } from 'vue'
import Browser from '@/components/Browser.vue'
import BusinessTable from '@/components/BusinessTable.vue'
import AgencySelector from '@/components/AgencySelector.vue'
import { ElMessage } from 'element-plus'
import officers from '@/api/lawenforcement/Officer.js'
import agencies from '@/api/lawenforcement/Agency.js'
const busiTable = ref(null)
const phoneValidator = (rule, value, callback) => {
if (!value) return callback()
const mobile = /^(?:\+?86)?1[3-9]\d{9}$/
const landline = /^(\d{3,4}-?)?\d{7,8}$/
if (mobile.test(value) || landline.test(value)) return callback()
callback(new Error('联系电话格式不正确'))
}
async function handleDialogOk(formRef) {
const doValidate = () => new Promise((resolve) => {
if (!formRef) return resolve(true)
formRef.validate((valid) => resolve(valid))
})
const valid = await doValidate()
if (!valid) return
dialogConfig.value.loading = true
let res
try {
const payload = { ...dialogConfig.value.data }
payload.agencyId = payload.agency?.agencyId || payload.agencyId || null
delete payload.agency
if (dialogConfig.value.mode === 'add') {
res = await officers.add(payload)
} else if (dialogConfig.value.mode === 'modify') {
res = await officers.modify(payload[apiConfig.value.modelId], payload)
}
if (res?.success) {
dialogConfig.value.loading = false
dialogConfig.value.show = false
actions.value.query()
return
}
throw new Error('操作失败')
} catch (e) {
ElMessage.error(e.message || '操作失败')
} finally {
dialogConfig.value.loading = false
}
}
const state = reactive({
componentLoading: false,
permissions: {
query: true,
add: true,
modify: true,
detail: true,
delete: true,
deleteAll: true,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false,
canDeleteCustom: () => true,
canModifyCustom: () => true,
canDetailCustom: () => true,
},
tableConfig: {
hasControlColumn: true,
controlWidth: '220',
tableLoading: false,
multipleSelect: true,
},
apiConfig: {
api: officers,
modelId: 'officerId',
},
dialogConfig: {
type: 'min',
show: false,
mode: 'detail',
formLabelWidth: '120px',
baseTitle: '执法人员',
loading: false,
rules: {
officerName: [
{ required: true, message: '姓名不能为空', trigger: 'blur' },
{ min: 1, max: 100, message: '姓名长度为1-100个字符', trigger: 'blur' }
],
lawNo: [
{ required: true, message: '执法号不能为空', trigger: 'blur' },
{ min: 1, max: 50, message: '执法号长度为1-50个字符', trigger: 'blur' }
],
contactPhone: [
{ validator: phoneValidator, trigger: 'blur' },
{ min: 0, max: 20, message: '联系电话长度不能超过20个字符', trigger: 'blur' }
],
certificateNo: [
{ min: 0, max: 50, message: '系统用户ID长度不能超过50个字符', trigger: 'blur' }
],
agency: [
{ required: true, message: '所属机构不能为空', trigger: 'change' }
]
},
data: {},
actions: { handleDialogOk }
},
actions: {
add: handleAdd,
detail: handleDetail,
modify: handleModify,
},
queryParams: {}
})
const {
componentLoading,
permissions,
tableConfig,
apiConfig,
dialogConfig,
actions,
queryParams,
} = toRefs(state)
async function handleAdd() {
dialogConfig.value.mode = 'add'
dialogConfig.value.title = '新增执法人员'
dialogConfig.value.data = {
officerId: null,
officerName: '',
lawNo: '',
contactPhone: '',
certificateNo: '',
agencyId: null,
agency: null,
}
dialogConfig.value.show = true
}
async function handleDetail(row) {
dialogConfig.value.data = {}
dialogConfig.value.title = '详情执法人员'
dialogConfig.value.show = true
dialogConfig.value.mode = 'detail'
dialogConfig.value.showFooter = false
dialogConfig.value.loading = true
try {
const res = await officers.findOne(row[apiConfig.value.modelId])
if (!res?.success) throw new Error('接口返回数据异常')
const data = res.data || {}
if (!data.agency && data.agencyId) {
try {
const a = await agencies.findOne(data.agencyId)
if (a?.success) data.agency = a.data
} catch (_) {}
}
dialogConfig.value.data = data
} catch (e) {
ElMessage.error(e.message || '详情加载失败')
} finally {
dialogConfig.value.loading = false
}
}
async function handleModify(row) {
dialogConfig.value.data = {}
dialogConfig.value.title = '修改执法人员'
dialogConfig.value.show = true
dialogConfig.value.mode = 'modify'
dialogConfig.value.loading = true
try {
const res = await officers.findOne(row[apiConfig.value.modelId])
if (!res?.success) throw new Error('接口返回数据异常')
const data = res.data || {}
if (!data.agency && data.agencyId) {
try {
const a = await agencies.findOne(data.agencyId)
if (a?.success) data.agency = a.data
} catch (_) {}
}
dialogConfig.value.data = data
} catch (e) {
ElMessage.error(e.message || '详情加载失败')
} finally {
dialogConfig.value.loading = false
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,185 @@
<template>
<browser :component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
:default-query-params="queryParams"
@update:query-params="queryParams = $event"
@update:actions="actions = $event"
@update:dialog-config="dialogConfig = $event">
<template #queryPanel="{ queryParams: qp }">
<el-form ref="queryForm" :model="qp" label-width="100px">
<el-row class="query-condition">
<el-col :span="6">
<el-form-item label="方式名称" prop="methodName">
<el-input v-model="qp.methodName"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="方式描述" prop="description">
<el-input v-model="qp.description"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="是否删除" prop="isDeleted">
<el-select v-model="qp.isDeleted" placeholder="请选择" clearable>
<el-option v-for="item in DICTITEMS.SF_OPTIONS" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<el-table-column prop="methodName" label="方式名称" min-width="200"/>
<el-table-column prop="description" label="方式描述" min-width="500" show-overflow-tooltip/>
<el-table-column prop="enabled" label="启用状态" min-width="200">
<template #default="scope">
<el-switch v-model="scope.row.enabled"
@change="updateEnabled(scope.row)"
:disabled="scope.row.isDeleted"
:active-value="true"
:inactive-value="false"
active-text="启用"
inactive-text="停用"
active-color="#13ce66"
inactive-color="#ff4949"/>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="200"/>
<template #dialogContent="{ dialogConfig: dc }">
<el-row :disabled="true">
<el-col :span="16">
<el-form-item label="方式名称" prop="methodName">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.methodName"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="方式描述" prop="description">
<el-input :disabled="dc.mode === 'detail'" type="textarea" v-model="dc.data.description"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否启用" prop="enabled">
<el-switch :disabled="dc.mode === 'detail'" v-model="dc.data.enabled" :active-value="true"
:inactive-value="false" active-text="启用" inactive-text="停用" active-color="#13ce66"
inactive-color="#ff4949"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item v-if="dc.mode ==='detail'" label="更新时间" prop="updateTime">
<el-input :disabled="true" v-model="dc.data.updateTime"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item v-if="dc.mode ==='detail'" label="创建时间" prop="createTime">
<el-input :disabled="true" v-model="dc.data.createTime"/>
</el-form-item>
</el-col>
</el-row>
</template>
</browser>
</template>
<script setup>
import {reactive, toRefs} from 'vue'
import Browser from '@/components/Browser.vue'
import {useUserStore} from '@/stores/modules/user'
import deliveryMethods from "@/api/lawenforcement/DeliveryMethod.js"
import {ElMessage} from "element-plus"
import {DICTITEMS} from "@/utils/Constants.js";
const userStore = useUserStore()
const state = reactive({
componentLoading: false,
permissions: {
query: true,
add: true,
modify: true,
detail: true,
delete: true,
deleteAll: true,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false,
canDeleteCustom: (row) => {
return !row.isDeleted
},
canModifyCustom: (row) => {
return !row.isDeleted
}
},
tableConfig: {
hasControlColumn: true,
controlWidth: '150',
tableLoading: false
},
apiConfig: {
api: deliveryMethods,
modelId: 'deliveryMethodId',
},
dialogConfig: {
show: false,
mode: 'detail',
formLabelWidth: '110px',
baseTitle: '送达方式',
loading: false,
rules: {
methodName: [{required: true, message: '方式名称不能为空', trigger: 'change'}, {
min: 0,
max: 500,
message: '方式名称不能超过2',
trigger: 'change'
}],
description: [{min: 0, max: 2000, message: '方式描述不能超过100', trigger: 'change'}],
enabled: [{required: true, message: '是否启用不能为空', trigger: 'change'}]
},
data: {},
actions: {}
},
actions: {
add: handleAdd
},
queryParams: {isDeleted: '0'}
})
const {
componentLoading,
permissions,
tableConfig,
apiConfig,
dialogConfig,
actions,
queryParams,
selectConfig
} = toRefs(state)
function handleAdd() {
dialogConfig.value.mode = 'add'
dialogConfig.value.title = '新增送达方式'
dialogConfig.value.data = {
enabled: true
}
dialogConfig.value.show = true
}
function updateEnabled(row) {
tableConfig.value.tableLoading = true
apiConfig.value.api.modify(row[apiConfig.value.modelId], row).then(rs => {
tableConfig.value.tableLoading = false
actions.value.query()
if (rs.success) {
ElMessage.success('操作成功')
} else {
throw new Error('操作失败')
}
})
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,174 @@
<template>
<browser :component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
:default-query-params="queryParams"
@update:query-params="queryParams = $event"
@update:dialog-config="dialogConfig = $event">
<template #queryPanel="{ queryParams: qp }">
<el-form ref="queryForm" :model="qp" label-width="80px">
<el-row class="query-condition">
<el-col :span="8">
<el-form-item label="属地">
<AgencySelector v-model="qp.agency" :lazy-load="true"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<el-table-column header-align="center" align="center" type="index" label="序号" min-width="80"/>
<el-table-column header-align="center" align="center" prop="agencyName" label="属地" min-width="250"/>
<el-table-column header-align="center" align="center" label="总数" prop="total" min-width="150"
class-name="can-click"/>
<!-- 字段名一定要放在第一行-->
<el-table-column header-align="center" align="center"
v-for="col in allCols"
:prop="col.deliveryMethodId"
:key="col.deliveryMethodId"
:label="col.methodName"
width="150"
class-name="can-click"/>
<template #dialog="{ dialogConfig: dc }">
<el-dialog :open="dc.show" :title="dc.title" :type="dc.type" v-if="dc.show" :show-footer="false"
@update:open="dc.show = false">
<zfwsxx :dialog-data="dc.data" :is-not-dialog="false" style="height: 600px;"/>
</el-dialog>
</template>
</browser>
</template>
<script setup>
import {reactive, toRefs, ref, nextTick} from 'vue'
import Browser from '@/components/Browser.vue'
import deliveryMethods from "@/api/lawenforcement/DeliveryMethod.js"
import deliveryRecords from "@/api/lawenforcement/DeliveryRecord.js"
import AgencySelector from "@/components/AgencySelector.vue"
import ElDialog from "@/components/ElDialog/index.vue"
import Zfwsxx from "@pages/zfwssd/zfwsxx.vue"
const state = reactive({
componentLoading: false,
permissions: {
query: true,
add: false,
modify: false,
detail: false,
delete: false,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false
},
tableConfig: {
tableData: [],
tableLoading: false,
usePage: false,
multipleSelect: false,
hasControlColumn: false,
controlWidth: '150',
lazy: true,
rowKey: 'agencyCode',
treeProps: {children: 'children', hasChildren: 'hasChildren'},
load: load,
cellClick: caseEventClick
},
apiConfig: {
tableLoading: false,
api: deliveryRecords,
modelId: 'deliveryId',
},
dialogConfig: {
show: false,
mode: 'detail',
loading: false,
data: {},
actions: {},
},
actions: {
query: handleQuery
},
queryParams: {}
})
const allIds = ref([])
const allCols = ref([])
const {componentLoading, queryParams, permissions, tableConfig, apiConfig, dialogConfig, actions} = toRefs(state)
function handleQuery() {
tableConfig.value.tableLoading = true
if (queryParams.value.agency) {
queryParams.value = Object.assign({}, {
agencyCode: queryParams.value.agency.agencyCode,
agencyLevel: queryParams.value.agency.agencyLevel
})
} else {
queryParams.value = Object.assign({}, {
agencyCode: null,
agencyLevel: null
})
}
tableConfig.value.tableData = {success: true, data: [], total: 0}
nextTick(() => {
apiConfig.value.api.statistics(queryParams.value).then(res => {
if (res.success) {
tableConfig.value.tableData = res
}
tableConfig.value.tableLoading = false
}).catch(() => {
tableConfig.value.tableLoading = false
})
})
}
function load(tree, treeNode, resolve) {
tableConfig.value.tableLoading = true
queryParams.value.agencyLevel = tree.agencyLevel + 1
queryParams.value.agencyCode = tree.agencyCode
apiConfig.value.api.statistics(queryParams.value).then(res => {
if (res.success) {
resolve(res.data)
}
tableConfig.value.tableLoading = false
}).catch(() => {
tableConfig.value.tableLoading = false
})
}
function caseEventClick(row, column, cell, event) {
const colProp = column.property
let keys = allCols.value.map(o => o.deliveryMethodId)
keys.push('total')
if (keys.includes(colProp)) {
dialogConfig.value.show = true
dialogConfig.value.mode = 'detail'
dialogConfig.value.title = '执法文书列表'
dialogConfig.value.loading = false
let prop = colProp
if ('total' === colProp) prop = ''
dialogConfig.value.data = {deliveryMethodId: prop, agencyCode: row.agencyCode, show: false}
}
}
function init() {
tableConfig.value.tableLoading = true
deliveryMethods.querylist({isDeleted: false, enabled: true}).then(res => {
let arr = []
allIds.value = res.data.map(v => v.deliveryMethodId);
allIds.value.push('total')
allCols.value = [...res.data]
tableConfig.value.tableLoading = false
}).catch(() => {
tableConfig.value.tableLoading = false
})
}
init()
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,170 @@
<template>
<browser :component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
:default-query-params="queryParams"
@update:query-params="queryParams = $event"
@update:actions="actions = $event"
@update:dialog-config="dialogConfig = $event">
<template #queryPanel="{ queryParams: qp }">
<el-form ref="queryForm" :model="qp" label-width="100px">
<el-row class="query-condition">
<el-col :span="6">
<el-form-item label="姓名" prop="name">
<el-input v-model="qp.name" clearable/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="联系电话" prop="phone">
<el-input v-model="qp.phone" clearable/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="住址" prop="address">
<el-input v-model="qp.address" clearable/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="是否删除" prop="isDeleted">
<el-select v-model="qp.isDeleted" placeholder="请选择" clearable>
<el-option v-for="item in DICTITEMS.SF_OPTIONS" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<el-table-column prop="name" label="姓名" min-width="120"/>
<el-table-column prop="sexName" label="性别" sort-by="sex" min-width="120"/>
<el-table-column prop="phone" label="电话号码" min-width="150"/>
<el-table-column prop="email" label="电子邮件" min-width="160"/>
<el-table-column prop="wechatId" label="微信ID" min-width="150"/>
<el-table-column prop="address" label="住址" min-width="250"/>
<template #dialogContent="{ dialogConfig: dc }">
<el-row :disabled="true">
<el-col :span="8">
<el-form-item label="姓名" prop="name">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.name"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="性别" prop="sex">
<DictSelector :disabled="dc.mode === 'detail'" v-model="dc.data.sex" dict-code="DE01900" :multiple="false"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话号码" prop="phone">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.phone"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电子邮件" prop="email">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.email"/>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="住址" prop="address">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.address"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="微信ID" prop="wechatId">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.wechatId"/>
</el-form-item>
</el-col>
</el-row>
</template>
</browser>
</template>
<script setup>
import {reactive, toRefs} from 'vue'
import Browser from '@/components/Browser.vue'
import {useUserStore} from '@/stores/modules/user'
import recipientInfos from "@/api/lawenforcement/RecipientInfo.js";
import DictSelector from "@/components/DictSelector.vue";
import {DICTITEMS} from "@/utils/Constants.js";
const userStore = useUserStore()
const state = reactive({
componentLoading: false,
permissions: {
query: true,
add: true,
modify: true,
detail: true,
delete: true,
deleteAll: true,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false,
canDeleteCustom: (row) => {
return !row.isDeleted
},
canModifyCustom: (row) => {
return !row.isDeleted
}
},
tableConfig: {
hasControlColumn: true,
controlWidth: '150',
tableLoading: false,
multipleSelect: true
},
apiConfig: {
api: recipientInfos,
modelId: 'recipientId'
},
dialogConfig: {
show: false,
mode: 'detail',
baseTitle: '受送人',
formLabelWidth: '90px',
loading: false,
rules: {
name: [
{required: true, message: '姓名不能为空', trigger: 'change'},
{min: 0, max: 30, message: '姓名不能超过30', trigger: 'change'}
],
sex: [{required: true, message: '性别不能为空', trigger: 'change'}],
phone: [
{required: true, message: '电话号码不能为空', trigger: 'change'},
{min: 0, max: 20, message: '电话号码不能超过20', trigger: 'change'},
{pattern: /^1[3-9]\d{9}$/, message: '请输入有效的电话号码', trigger: 'blur'}
],
email: [
{required: true, message: '电子邮件不能为空', trigger: 'change'},
{min: 0, max: 30, message: '电子邮件不能超过30', trigger: 'change'},
{
pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message: '请输入有效的电子邮件地址',
trigger: 'blur'
}
],
address: [
{required: true, message: '住址不能为空', trigger: 'change'},
{min: 0, max: 200, message: '住址不能超过200', trigger: 'change'}
],
wechatId: [
{required: true, message: '微信ID不能为空', trigger: 'change'},
{min: 0, max: 50, message: '微信ID不能超过50', trigger: 'change'}
]
},
data: {},
actions: {}
},
actions: {},
queryParams: {isDeleted: '0'}
})
const {componentLoading, permissions, tableConfig, apiConfig, dialogConfig, actions, queryParams} = toRefs(state)
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,478 @@
<template>
<browser :component-loading="componentLoading"
:api-config="apiConfig"
:table-config="tableConfig"
:permissions="permissions"
:dialog-config="dialogConfig"
:actions="actions"
@update:query-params="queryParams = $event"
@update:actions="actions = $event"
@update:dialog-config="dialogConfig = $event">
<template #extraButton v-if="isNotDialog">
<el-button type="success" @click="handleSms" :disabled="deliverys.length === 0">
<template #icon>
<font-awesome-icon icon="file-export"/>
</template>
短信推送 ({{ deliverys.length }})
</el-button>
</template>
<template #queryPanel="{ queryParams: qp }" v-if="isNotDialog">
<el-form ref="queryForm" :model="qp" label-width="80px">
<el-row class="query-condition">
<el-col :span="6">
<el-form-item label="案卷名称">
<SimpleEntitySelector v-model="qp.caseId" :simpleConfig="simpleConfigCase"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="受送达人">
<SimpleEntitySelector v-model="qp.recipientId" :simpleConfig="simpleConfigSdfs"/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="送达方式">
<SimpleEntitySelector v-model="qp.deliveryMethodId" :simpleConfig="simpleConfigSsr"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<el-table-column prop="caseInfo.caseNum" label="案卷编号" min-width="200"/>
<el-table-column prop="caseInfo.caseName" label="案卷名称" min-width="350" show-overflow-tooltip/>
<el-table-column prop="documentInfo.documentName" label="文书名称" min-width="200"/>
<el-table-column prop="deliveryMethod.methodName" label="送达方式" min-width="100"/>
<el-table-column prop="recipientInfo.name" label="受送人" min-width="100"/>
<el-table-column prop="deliveryTime" label="实际送达时间" min-width="150"/>
<el-table-column prop="status" label="状态" min-width="100">
<template #default="{ row }">
<span v-if="row.status!=='1'">正常送达</span><span v-else>留置送达</span></template>
</el-table-column>
<template #tableControlColumn="{data: r}">
<el-link v-if="r.data.row.needCll && isNotDialog" type="primary" @click="handleVoicePush(r.data.row)"
title="语音推送">语音推送
</el-link>
</template>
<template #dialogContent="{ dialogConfig: dc }">
<el-row>
<el-col :span="24">
<el-form-item label="案卷名称" prop="caseId">
<SimpleEntitySelector :disabled="dc.mode === 'detail'" @change="ajxxChange" v-model="dc.data.caseId"
:simpleConfig="simpleConfigCase"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="执法文书" prop="documentId">
<SimpleEntitySelector :disabled="dc.mode === 'detail'" v-model="dc.data.documentId"
:simpleConfig="simpleConfigZfws" :caseId="dc.data.caseId"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="受送达人" prop="recipientId">
<SimpleEntitySelector :disabled="dc.mode === 'detail'" :simpleConfig="simpleConfigSdfs" :multiple="false"
v-model="dc.data.recipientId"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="送达方式" prop="deliveryMethodId">
<SimpleEntitySelector :disabled="dc.mode === 'detail'" @change="sdfsChange" :simpleConfig="simpleConfigSsr"
:multiple="false" v-model="dc.data.deliveryMethodId"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实际送达时间" prop="deliveryTime">
<el-date-picker :disabled="dc.mode === 'detail'" v-model="dc.data.deliveryTime" type="datetime"
placeholder="选择实际送达时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%;"/>
</el-form-item>
</el-col>
<!-- <el-col :span="8"><el-form-item label="送达回证" prop="receiptProof"><el-input :disabled="dc.mode === 'detail'" v-model="dc.data.receiptProof"/></el-form-item></el-col>-->
<el-col :span="8" v-if="methodName === '电话送达'">
<el-form-item label="通话录音" prop="callTape">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.callTape"/>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName === '电子送达'">
<el-form-item label="送达类型" prop="deliveryType">
<el-select :disabled="dc.mode === 'detail'" v-model="dc.data.deliveryType" placeholder="请选择" clearable>
<el-option v-for="item in sdlxOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName === '邮寄送达'">
<el-form-item label="快递单号" prop="trackingNo">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.trackingNo"/>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName === '邮寄送达'">
<el-form-item label="物流信息" prop="logistics.info">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.logistics.info"/>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName === '公告送达'">
<el-form-item label="刊登凭证" prop="appearedVoucher">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.appearedVoucher"/>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName === '委托送达' || methodName === '转交送达'">
<el-form-item label="委托人姓名" prop="trusteeName">
<el-input :disabled="dc.mode === 'detail'" v-model="dc.data.trusteeName"/>
</el-form-item>
</el-col>
<el-col :span="8" v-if="methodName !== '公告送达'">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="dc.data.status" :disabled="dc.mode === 'detail'">
<el-radio :label="'0'" :value="'0'">正常送达</el-radio>
<el-radio :label="'1'" :value="'1'">留置送达</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="methodName">
<!-- v-if="methodName && (methodName === '直接送达' || methodName === '转交送达' || methodName === '留置送达')"-->
<el-form-item label="送达回证">
<MultiplePicture ref="multiple_pictures"
:form-data="{urls: dc.data.picList}"
:parameters="{mode: dc.mode, autoUpload: true, limit: 20}"
@on-success="onSuccess"
@on-pic-view="onPicView"
@on-remove="onRemove"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="送达人电子签名" prop="recipientSignature">
<el-button type="primary" size="small" @click="openSignatureOne" v-if="dc.mode !== 'detail'">送达人电子签名
</el-button>
<div v-if="dc.data.recipientSignature"
style="border: 1px solid #ccc; margin-left: 10px; display: inline-block; position: relative;">
<img :src="dc.data.recipientSignature" alt="签名" style="height: 100px;"/>
<el-button v-if="dc.mode !== 'detail'" type="danger" size="small"
style="position: absolute; top: 5px; right: 5px; transform: translate(50%, -50%); border-radius: 50%; width: 20px; height: 20px; padding: 0;"
@click="saveSignatureOne('')">×
</el-button>
</div>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="见证人电子签名" prop="witnessSignature">
<el-button type="primary" size="small" @click="openSignatureTwo" v-if="dc.mode !== 'detail'">见证人电子签名
</el-button>
<div v-if="dc.data.witnessSignature"
style="border: 1px solid #ccc; margin-left: 10px; display: inline-block; position: relative;">
<img :src="dc.data.witnessSignature" alt="签名" style="height: 100px;"/>
<el-button v-if="dc.mode !== 'detail'" type="danger" size="small"
style="position: absolute; top: 5px; right: 5px; transform: translate(50%, -50%); border-radius: 50%; width: 20px; height: 20px; padding: 0;"
@click="saveSignatureTwo('')">×
</el-button>
</div>
</el-form-item>
</el-col>
<PictureView ref="pictureViewRef"/>
</el-row>
</template>
</browser>
<SignatureComponent v-model="showSignatureOne" @save="saveSignatureOne"/>
<SignatureComponent v-model="showSignatureTwo" @save="saveSignatureTwo"/>
</template>
<script setup>
import {reactive, toRefs, ref, watch, onMounted} from 'vue'
import Browser from '@/components/Browser.vue'
import {ElButton, ElMessage} from "element-plus"
import deliveryRecords from "@/api/lawenforcement/DeliveryRecord.js"
import SimpleEntitySelector from "@/components/SimpleEntitySelector.vue"
import MultiplePicture from "@pages/common/MultiplePicture.vue"
import PictureView from "@pages/common/PictureView.vue"
import SignatureComponent from "@pages/common/SignatureComponent.vue"
const props = defineProps({
dialogData: {type: Object, default: () => ({})},
isNotDialog: {type: Boolean, default: true}
})
const state = reactive({
componentLoading: false,
permissions: {
query: props.isNotDialog,
add: props.isNotDialog,
modify: props.isNotDialog,
detail: true,
delete: props.isNotDialog,
deleteAll: props.isNotDialog,
importFile: false,
exportFile: false,
exportSelectFile: false,
downloadTemp: false,
},
tableConfig: {
tableData: {},
hasControlColumn: true,
controlWidth: props.isNotDialog ? '180' : '80',
multipleSelect: props.isNotDialog,
selectable: (row) => {
return row.deliveryMethod?.methodName === '电子送达' && row.deliveryType === '2'
}
},
apiConfig: {
api: deliveryRecords,
modelId: 'deliveryId',
},
dialogConfig: {
show: false,
mode: 'detail',
formLabelWidth: '110px',
loading: false,
baseTitle: '执法文书送达',
rules: {
caseId: [{required: true, message: '案卷不能为空', trigger: 'change'}],
documentIds: [{required: true, message: '执法文书不能为空', trigger: 'change'}],
recipientId: [{required: true, message: '受送达人不能为空', trigger: 'change'}],
deliveryMethodId: [{required: true, message: '送达方式不能为空', trigger: 'change'}],
deliveryTime: [{required: false, message: '实际送达时间不能为空', trigger: 'change'}],
receiptProof: [{required: false, message: '送达回证不能为空', trigger: 'change'}, {
min: 0,
max: 255,
message: '送达回证的长度不能超过255',
trigger: 'change'
}],
callTape: [{required: false, message: '通话录音不能为空', trigger: 'change'}, {
min: 0,
max: 100,
message: '通话录音的长度不能超过100',
trigger: 'change'
}],
deliveryType: [{required: true, message: '送达类型不能为空', trigger: 'change'}],
trackingNo: [{required: false, message: '快递单号不能为空', trigger: 'change'}, {
min: 0,
max: 100,
message: '快递单号的长度不能超过100',
trigger: 'change'
}],
logistics: [{required: false, message: '物流信息不能为空', trigger: 'change'}],
appearedVoucher: [{required: false, message: '刊登凭证不能为空', trigger: 'change'}, {
min: 0,
max: 100,
message: '刊登凭证的长度不能超过100',
trigger: 'change'
}],
trusteeName: [{required: false, message: '委托人姓名不能为空', trigger: 'change'}, {
min: 0,
max: 20,
message: '委托人姓名的长度不能超过20',
trigger: 'change'
}]
},
data: {},
actions: {
handleDialogOk: handleDialogOk
}
},
actions: {
add: handleAdd,
modify: handleModify,
detail: handleDetail,
query: handleQuery,
handleSelectionChange
},
simpleConfigCase: {confName: 'case', parmas: {tag: 'Y'}},
simpleConfigZfws: {confName: 'document'},
simpleConfigSdfs: {confName: 'recipient'},
simpleConfigSsr: {confName: 'method'},
deliverys: [],
queryParams: {}
})
const {
componentLoading,
permissions,
tableConfig,
apiConfig,
dialogConfig,
actions,
simpleConfigCase,
simpleConfigZfws,
simpleConfigSdfs,
simpleConfigSsr,
deliverys,
queryParams
} = toRefs(state)
const sdlxOptions = reactive([{value: '1', label: '网站'}, {value: '2', label: '短信'}, {
value: '3',
label: '邮件'
}, {value: '4', label: '手机APP'}, {value: '5', label: '微信'}])
const methodName = ref('')
const caseId = ref('')
function sdfsChange(row) {
methodName.value = row?.methodName
if (methodName.value === '公告送达') {
dialogConfig.value.data.status = 0
}
}
function ajxxChange(row) {
caseId.value = row?.caseId
}
function handleQuery() {
tableConfig.value.tableLoading = true
apiConfig.value.api.query(props.isNotDialog ? queryParams.value : props.dialogData).then(res => {
if (res.success) {
tableConfig.value.tableData = res
}
tableConfig.value.tableLoading = false
}).catch(() => tableConfig.value.tableLoading = false)
}
function handleAdd() {
dialogConfig.value.show = true
methodName.value = null
dialogConfig.value.mode = 'add'
dialogConfig.value.title = '新增执法文书送达'
dialogConfig.value.data = Object.assign({}, {documentIds: [], materials: [], picList: [], logistics: {}, status: '0'})
}
function handleModify(row) {
dialogConfig.value.show = true
methodName.value = null
dialogConfig.value.mode = 'modify'
dialogConfig.value.title = '修改执法文书送达'
dialogConfig.value.data.documentIds = []
findOne(row)
}
function handleDetail(row) {
dialogConfig.value.show = true
methodName.value = null
dialogConfig.value.mode = 'detail'
dialogConfig.value.title = '执法文书送达详情'
dialogConfig.value.showFooter = false
findOne(row)
}
function findOne(row) {
dialogConfig.value.loading = true
apiConfig.value.api.findOne(row[apiConfig.value.modelId]).then(res => {
if (res.success) {
dialogConfig.value.loading = false
let data = res.data
caseId.value = data.caseId
methodName.value = data.deliveryMethod?.methodName
data.logistics = data.logistics ? data.logistics : {}
data.documentIds = data.documentIds?.split(',') || []
if (data.materials) data.materials.forEach(item => item.uid = item.materialsId)
dialogConfig.value.data = Object.assign({}, data, {picList: data.materials})
} else {
dialogConfig.value.loading = false
throw new Error('查询失败')
}
}).catch(() => {
dialogConfig.value.loading = false
})
}
function handleDialogOk(formRef) {
let _event = actions.value
formRef.validate(valid => {
if (valid) {
dialogConfig.value.loading = true
let data = Object.assign({}, dialogConfig.value.data)
if (dialogConfig.value.mode === 'add') {
apiConfig.value.api.add(data).then(res => {
dialogConfig.value.show = false
if (res.success) {
ElMessage.success('操作成功')
_event.query()
} else {
throw new Error('操作失败')
}
dialogConfig.value.loading = false
}).catch(() => {
dialogConfig.value.loading = false
})
} else if (dialogConfig.value.mode === 'modify') {
apiConfig.value.api.modify(dialogConfig.value.data[apiConfig.value.modelId], data).then(res => {
dialogConfig.value.show = false
if (res.success) {
ElMessage.success('操作成功')
_event.query()
} else {
throw new Error('操作失败')
}
dialogConfig.value.loading = false
}).catch(() => {
dialogConfig.value.loading = false
})
}
}
})
}
function handleSelectionChange(selectedData) {
deliverys.value = [...selectedData]
}
function handleVoicePush(row) {
tableConfig.value.tableLoading = true
apiConfig.value.api.voicePush(row).then(res => {
if (res.success) {
ElMessage.success('操作成功')
} else {
throw new Error('操作失败')
}
tableConfig.value.tableLoading = false
}).catch(() => {
tableConfig.value.tableLoading = false
})
}
function handleSms() {
let ids = deliverys.value.map((item) => item[apiConfig.value.modelId])
tableConfig.value.tableLoading = true
apiConfig.value.api.smsCall(ids).then(res => {
if (res.success) {
ElMessage.success('操作成功')
} else {
throw new Error('操作失败')
}
tableConfig.value.tableLoading = false
}).catch(() => {
tableConfig.value.tableLoading = false
})
}
function onSuccess(data, file, row) {
let obj = {materialsId: file.uid, name: data.fileName, savePath: data.savePathName, url: data.url}
dialogConfig.value.data.materials.push(obj)
}
function onRemove(file, row) {
const idx = dialogConfig.value.data.materials.findIndex((item) => item.uid === file.uid)
if (idx > -1) dialogConfig.value.data.materials.splice(idx, 1)
}
const pictureViewRef = ref(null)
function onPicView(url) {
pictureViewRef.value.viewPicture(url)
}
const showSignatureOne = ref(false)
const openSignatureOne = () => {
showSignatureOne.value = true
}
const saveSignatureOne = (data) => {
dialogConfig.value.data.recipientSignature = data
}
const showSignatureTwo = ref(false)
const openSignatureTwo = () => {
showSignatureTwo.value = true
}
const saveSignatureTwo = (data) => {
dialogConfig.value.data.witnessSignature = data
}
</script>
<style lang="scss" scoped>
</style>