Browse Source

fit: 警员中心-警员新增头像、人员属性、婚姻状况、子女等属性。

fit: 新增基础数据国家信访投诉。
fit: 新增基础数据公安部信访投诉。
main
wxc 1 year ago
parent
commit
cd07154596
  1. 0
      public/a.json
  2. BIN
      public/mp4/1.ts
  3. 22
      src/api/data/petitionComplaint.ts
  4. 11
      src/api/request.ts
  5. 14
      src/api/system/depart.ts
  6. 7
      src/api/system/holiday.ts
  7. 9
      src/api/work/negative.ts
  8. 8
      src/api/work/negativeTask.ts
  9. 2
      src/components/home/work/my-todo.vue
  10. 23
      src/components/negative/add.vue
  11. 2
      src/components/police-select.vue
  12. 28
      src/enums/dictEnums.ts
  13. 2
      src/permission.ts
  14. 273
      src/views/data/Gabxf.vue
  15. 342
      src/views/data/Gjxf.vue
  16. 0
      src/views/data/PetitionComplaintExcel.vue
  17. 6
      src/views/sensitivePerception/ClueData.vue
  18. 310
      src/views/system/Depart.vue
  19. 3
      src/views/system/Dict.vue
  20. 85
      src/views/system/Holiday.vue
  21. 179
      src/views/system/Police.vue
  22. 141
      src/views/work/NegativeTask.vue
  23. 73
      src/views/work/Query.vue
  24. 2
      src/views/work/Todo.vue
  25. 3
      vite.config.ts

0
public/a.json

BIN
public/mp4/1.ts

Binary file not shown.

22
src/api/data/petitionComplaint.ts

@ -0,0 +1,22 @@
import request from "@/api/request";
export function importPetitionComplaint(body) {
return request.post({
url: '/data/petitionComplaint/import',
body
});
}
export function listPetitionComplaint(query) {
return request.get({
url: '/data/petitionComplaint',
query
});
}
export function addPetitionComplaint(body, dataUpdateMethod) {
return request.post({
url: `/data/petitionComplaint/dataUpdateMethod/${dataUpdateMethod}`,
body
});
}

11
src/api/request.ts

@ -1,4 +1,4 @@
import { ElMessageBox } from 'element-plus'
import { getToken, deleteToken } from '@/utils/token'
import feedback from '@/utils/feedback'
@ -38,7 +38,7 @@ function del(options: Options) {
let isRelogin = false;
function ajax(url: string, options: Options) {
const headers: Record<string, string> = {
"Content-Type": "application/json",
"Authorization": getToken()
};
let body: string | FormData;
@ -65,9 +65,13 @@ function ajax(url: string, options: Options) {
}
}
if (options?.body) {
if (options.body instanceof String || options.body instanceof FormData) {
if (options.body instanceof FormData) {
body = options.body;
} else {
headers["Content-Type"] = "application/json"
if (options.body instanceof String) {
body = options.body;
}
if (options.body instanceof Array || (options.body instanceof Object && Object.keys(options.body).length > 0)) {
body = JSON.stringify(options.body);
}
@ -100,7 +104,6 @@ function ajax(url: string, options: Options) {
})
}
const request = {
get,
post,

14
src/api/system/depart.ts

@ -7,6 +7,13 @@ export function departTreeList(query) {
});
}
export function listDepart(query) {
return request.get({
url: '/depart/list',
query
});
}
export function departTree() {
return request.get({
url: '/depart/tree'
@ -38,3 +45,10 @@ export function updateDepart(body) {
body
});
}
export function delDepart(id) {
return request.del({
url: `/depart/${id}`
});
}

7
src/api/system/holiday.ts

@ -0,0 +1,7 @@
import request from "@/api/request";
export function listHolidays(year) {
return request.get({
url: `/holiday/${year}`
});
}

9
src/api/work/negative.ts

@ -34,3 +34,12 @@ export function generateOriginId(problemSourcesCode, businessTypeCode) {
url: `/negative/${problemSourcesCode}/${businessTypeCode}/generateOriginId`
});
}
export function negativeExport(query) {
return request.post({
url: `/negative/export/excel`,
query
});
}

8
src/api/work/negativeTask.ts

@ -0,0 +1,8 @@
import request from "@/api/request";
export function listNegativeTask(query) {
return request.get({
url: `/negativeTask`,
query
});
}

2
src/components/home/work/my-todo.vue

@ -24,7 +24,7 @@
class="add-btn"
><template #icon>
<icon name="el-icon-Plus" /> </template
>问题录入</el-button
>问题下发</el-button
>
</div>
<div class="table-container">

23
src/components/negative/add.vue

@ -155,6 +155,7 @@
item.dictValue === val
)[0].dictLabel)
"
clearable
>
<el-option
v-for="item in dict.policeType"
@ -187,8 +188,7 @@
</el-row>
<el-row
v-if="
form.problemSourcesCode === ProblemSources.XFTS ||
form.problemSourcesCode === ProblemSources.JWDC
ProblemSources_XFTS.includes(form.problemSourcesCode)
"
>
<el-col :span="12">
@ -236,10 +236,6 @@
<el-form-item
label="问题发生时间"
prop="happenTime"
v-if="
form.problemSourcesCode ===
ProblemSources.XFTS
"
>
<el-date-picker
v-model="form.happenTime"
@ -332,7 +328,7 @@
/>
<el-button
type="primary"
@click="form.departId = form.involveDepartId"
@click="handleLinkDepart"
text
>关联问题涉及单位</el-button
>
@ -481,6 +477,7 @@ import {
TimeLimit,
ApprovalFlow,
ProblemSources,
ProblemSources_XFTS
} from "@/enums/dictEnums";
import feedback from "@/utils/feedback";
import { addNegative, generateOriginId } from "@/api/work/negative";
@ -514,7 +511,12 @@ watch(
);
const formRef = ref(null);
async function handleAddNegative() {
await formRef.value.validate();
try {
await formRef.value.validate();
} catch(e) {
feedback.msgWarning('请检查输入项')
throw e
}
form.value.thingFiles = form.value.thingFiles.filter(
(item) => item.filePath
);
@ -575,6 +577,11 @@ function handleSelectInvolveProblem(vals) {
};
});
}
function handleLinkDepart() {
form.value.departId = form.value.involveDepartId
form.value.departName = form.value.involveDepartName
}
</script>
<style lang="scss" scoped>
.add-negation-container {

2
src/components/police-select.vue

@ -23,7 +23,7 @@
<span style="color: #999; font-size: 12px" class="mr-8">{{
item.empNo
}}</span>
<el-tag size="small">{{ item.position }}</el-tag>
<el-tag size="small" v-if="item.position">{{ item.position }}</el-tag>
</template>
</el-select-v2>
</div>

28
src/enums/dictEnums.ts

@ -36,22 +36,34 @@ export enum AssistCase {
// 问题来源
export enum ProblemSources {
// 信访投诉
XFTS = '1',
// 警务调查
JWDC = '2',
JWDC = 2,
// 警意调查
JYDC = '3',
JYDC = 3,
// 执法监督
JFZD = '4',
JFZD = 4,
// 360度网上测评
WSCP = '5',
WSCP = 5,
// 钉钉考勤
DDKQ = '6',
DDKQ = 6,
// 监督管理
JDGL = '7',
JDGL = 7,
// 国家信访平台
GJXFPT = 21,
// 公安部信访
GABXF = 22,
// 局长信箱
JZXX = 23,
// 12337信访
XF12337 = 24,
// 其他
XF_QT = 25
}
export const ProblemSources_XFTS = [ProblemSources.GJXFPT, ProblemSources.GABXF, ProblemSources.JZXX, ProblemSources.XF12337, ProblemSources.XF_QT]
// 主办层级
export enum HostLevel {
FIRST = '1',

2
src/permission.ts

@ -14,7 +14,7 @@ import 'nprogress/nprogress.css'
// NProgress配置
NProgress.configure({ showSpinner: false })
// 免登录白名单
const whiteList: string[] = [PageEnum.LOGIN]
const whiteList: string[] = [PageEnum.LOGIN, '/support']
router.beforeEach(async (to, from, next) => {
// 开始 Progress Bar
NProgress.start()

273
src/views/data/Gabxf.vue

@ -0,0 +1,273 @@
<template>
<div class="container">
<header>
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="投诉人">
<el-input
placeholder="请输入"
v-model="query.userName"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="mb-25 flex between">
<el-button type="primary" @click="show = true"
>公安部信访数据导入</el-button
>
<div>
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column label="信件编号" prop="originId" show-overflow-tooltip />
<el-table-column
label="投诉渠道"
prop="channelForFilingComplaints"
/>
<el-table-column label="受理层级" prop="acceptanceLevel" show-overflow-tooltip />
<el-table-column label="登记时间" width="discoveryTime" />
<el-table-column label="投诉人" prop="responderName" />
<el-table-column label="电话" prop="responderPhone" />
<el-table-column label="初重信访" prop="initialPetition" />
<el-table-column label="缠访闹访" prop="entanglementVisits" />
<el-table-column label="群众集访" prop="massVisits" />
<el-table-column label="涉嫌问题" prop="involveProblem" />
<el-table-column label="业务类别" prop="businessTypeName" />
<el-table-column label="具体内容" prop="thingDesc" show-overflow-tooltip />
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['user:edit']"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
v-model:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
>
</el-pagination>
</div>
</div>
<el-dialog title="公安部信访投诉数据导入" v-model="show" width="80vw">
<div style="min-height: 500px">
<template v-if="step === 1">
<el-radio-group v-model="templateType">
<el-radio value="1" size="large" border>国家信访</el-radio>
<el-radio value="2" size="large" border>公安部信访</el-radio>
<el-radio value="3" size="large" border>12337信访</el-radio>
</el-radio-group>
<div class="mt-20">
<span>信访投诉数据台账模板</span>
<a
class="link"
:href="`${BASE_PATH}/templates/信访投诉数据台账(模板).xlsx`"
target="__blank"
>下载</a
>
</div>
<el-upload
drag
:multiple="false"
:auto-upload="false"
:show-file-list="false"
v-model:file-list="fileList"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
class="mt-20"
>
<template v-if="fileList.length === 0">
<el-icon class="el-icon--upload"
><upload-filled
/></el-icon>
<div class="el-upload__text">
点击或拖拽文件到此区域上传
</div>
</template>
<template v-else>
<el-icon class="el-icon--upload"><Select /></el-icon>
<div class="el-upload__text">
已选择文件{{ fileList[fileList.length - 1].name }}
</div>
</template>
</el-upload>
</template>
<template v-else>
<el-page-header @back="step = 1" class="mb-20"></el-page-header>
<div class="table-container">
<el-table :data="importTableData" ref="tableRef">
<el-table-column type="selection" />
<el-table-column
label="信件编号"
prop="originId"
show-overflow-tooltip
/>
<el-table-column
label="投诉渠道"
prop="channelForFilingComplaints"
/>
<el-table-column
label="受理层级"
prop="acceptanceLevel"
/>
<el-table-column
label="登记时间"
prop="discoveryTime"
show-overflow-tooltip
/>
<el-table-column
label="投诉人"
prop="responderName"
width="90"
/>
<el-table-column
label="投诉人电话"
prop="contactPhone"
width="120"
/>
<el-table-column
label="初重信访"
prop="initialPetition"
align="center"
width="90"
/>
<el-table-column
label="缠访闹访"
prop="entanglementVisits"
width="90"
/>
<el-table-column
label="群众集访"
prop="massVisits"
width="90"
/>
<el-table-column
label="被投诉机构"
prop="complainedDepartName"
/>
<el-table-column
label="具体内容"
prop="thingDesc"
show-overflow-tooltip
/>
<el-table-column label="数据校验" width="120">
<template #default="{ row }">
<el-tag type="success">正确</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</template>
</div>
<footer class="flex end mt-20 v-center">
<span class="mr-20" v-if="step === 2">选中{{ checkRowSize }}</span>
<el-button size="large" @click="show = false">取消</el-button>
<el-button
type="primary"
size="large"
@click="handleImport"
:disabled="fileList.length === 0"
v-if="step === 1"
>下一步</el-button
>
<el-button
type="primary"
size="large"
@click="handleSaveImport"
:disabled="checkRowSize === 0"
v-else
>确认导入</el-button
>
</footer>
</el-dialog>
</template>
<script setup>
import { BASE_PATH } from "@/api/request";
import {
importPetitionComplaint,
listPetitionComplaint,
addPetitionComplaint
} from "@/api/data/petitionComplaint";
import feedback from '@/utils/feedback'
const query = ref({
size: 10,
current: 1,
});
const list = ref([]);
const total = ref(0);
function getList() {
listPetitionComplaint(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
});
}
getList()
function reset() {
query.value = {
size: 10,
current: 1,
};
getList();
}
const show = ref(false);
const templateType = ref("1");
const fileList = ref([]);
const importTableData = ref([]);
const step = ref(1);
async function handleImport() {
const formData = new FormData();
formData.append("file", fileList.value[fileList.value.length - 1].raw);
importTableData.value = await importPetitionComplaint(formData);
step.value = 2;
nextTick(() => {
tableRef.value.toggleAllSelection()
})
}
const checkRowSize = computed(() => tableRef.value?.getSelectionRows().length || 0)
const tableRef = ref(null)
async function handleSaveImport() {
const rows = tableRef.value.getSelectionRows()
console.log(rows)
await addPetitionComplaint([...rows])
feedback.msgSuccess(`成功导入${rows.length}条数据`)
show.value = false
getList()
}
</script>
<style lang="scss" scoped>
</style>

342
src/views/data/Gjxf.vue

@ -0,0 +1,342 @@
<template>
<div class="container">
<header>
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="信件编号">
<el-input
placeholder="请输入"
v-model="query.originId"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="投诉人">
<div class="flex gap">
<el-select
v-model="query.responderKey"
style="width: 160px"
@change="delete query.responderValue"
>
<el-option value="name" label="姓名" />
<el-option value="phone" label="电话" />
</el-select>
<el-input
placeholder="请输入"
v-model="query.responderValue"
clearable
/>
</div>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="登记时间">
<el-date-picker
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结束时间"
v-model="query.happenTime"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="具体内容">
<el-input
placeholder="请输入"
v-model="query.userName"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="mb-25 flex between">
<el-button type="primary" @click="show = true"
>国家信访数据导入</el-button
>
<div>
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</div>
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column
label="信件编号"
prop="originId"
show-overflow-tooltip
/>
<el-table-column
label="投诉渠道"
prop="channelForFilingComplaints"
/>
<el-table-column
label="受理层级"
prop="acceptanceLevel"
show-overflow-tooltip
/>
<el-table-column
label="登记时间"
width="discoveryTime"
show-overflow-tooltip
/>
<el-table-column
label="投诉人"
prop="responderName"
width="90"
/>
<el-table-column label="电话" prop="responderPhone" />
<el-table-column
label="初重信访"
prop="initialPetition"
align="center"
width="90"
/>
<el-table-column
label="缠访闹访"
prop="entanglementVisits"
align="center"
width="90"
/>
<el-table-column label="群众集访" prop="massVisits" />
<el-table-column label="涉嫌问题" prop="involveProblem" />
<el-table-column
label="涉及单位"
prop="involveProblem"
show-overflow-tooltip
/>
<el-table-column
label="具体内容"
prop="thingDesc"
show-overflow-tooltip
/>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button type="primary" link>核查情况</el-button>
<!-- <el-button
type="primary"
link
>问题核查</el-button
> -->
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
v-model:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
>
</el-pagination>
</div>
</div>
<el-dialog title="国家信访投诉 数据导入" v-model="show" width="80vw">
<div style="min-height: 500px">
<template v-if="step === 1">
<div class="mt-20">
<span>信访投诉数据台账模板</span>
<a
class="link"
:href="`${BASE_PATH}/templates/信访投诉数据台账(模板).xlsx`"
target="__blank"
>下载</a
>
</div>
<el-upload
drag
:multiple="false"
:auto-upload="false"
:show-file-list="false"
v-model:file-list="fileList"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
class="mt-20"
>
<template v-if="fileList.length === 0">
<el-icon class="el-icon--upload"
><upload-filled
/></el-icon>
<div class="el-upload__text">
点击或拖拽文件到此区域上传
</div>
</template>
<template v-else>
<el-icon class="el-icon--upload"><Select /></el-icon>
<div class="el-upload__text">
已选择文件{{ fileList[fileList.length - 1].name }}
</div>
</template>
</el-upload>
<el-radio-group v-model="dataUpdateMethod" class="mt-20">
<el-radio value="incremental" border>增量更新</el-radio>
<el-radio value="overwrite" border>覆盖更新</el-radio>
</el-radio-group>
</template>
<template v-else>
<el-page-header @back="step = 1" class="mb-20"></el-page-header>
<div class="table-container">
<el-table :data="importTableData" ref="tableRef">
<el-table-column type="selection" />
<el-table-column
label="信件编号"
prop="originId"
show-overflow-tooltip
/>
<el-table-column
label="投诉渠道"
prop="channelForFilingComplaints"
/>
<el-table-column
label="受理层级"
prop="acceptanceLevel"
/>
<el-table-column
label="登记时间"
prop="discoveryTime"
show-overflow-tooltip
/>
<el-table-column
label="投诉人"
prop="responderName"
width="90"
/>
<el-table-column
label="投诉人电话"
prop="contactPhone"
width="120"
/>
<el-table-column
label="初重信访"
prop="initialPetition"
align="center"
width="90"
/>
<el-table-column
label="缠访闹访"
prop="entanglementVisits"
width="90"
/>
<el-table-column
label="群众集访"
prop="massVisits"
width="90"
/>
<el-table-column
label="被投诉机构"
prop="complainedDepartName"
/>
<el-table-column
label="具体内容"
prop="thingDesc"
show-overflow-tooltip
/>
<el-table-column label="数据校验" width="120">
<template #default="{ row }">
<el-tag type="success">正确</el-tag>
</template>
</el-table-column>
</el-table>
</div>
</template>
</div>
<footer class="flex end mt-20 v-center">
<span class="mr-20" v-if="step === 2"
>选中{{ checkRowSize }}</span
>
<el-button size="large" @click="show = false">取消</el-button>
<el-button
type="primary"
size="large"
@click="handleImport"
:disabled="fileList.length === 0"
v-if="step === 1"
>下一步</el-button
>
<el-button
type="primary"
size="large"
@click="handleSaveImport"
:disabled="checkRowSize === 0"
v-else
>确认导入</el-button
>
</footer>
</el-dialog>
</template>
<script setup>
import { BASE_PATH } from "@/api/request";
import {
importPetitionComplaint,
listPetitionComplaint,
addPetitionComplaint,
} from "@/api/data/petitionComplaint";
import feedback from "@/utils/feedback";
const query = ref({
size: 10,
current: 1,
});
const list = ref([]);
const total = ref(0);
function getList() {
listPetitionComplaint(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
});
}
function reset() {
query.value = {
size: 10,
current: 1,
};
getList();
}
getList();
const show = ref(false);
const dataUpdateMethod = ref("incremental");
const fileList = ref([]);
const importTableData = ref([]);
const step = ref(1);
async function handleImport() {
const formData = new FormData();
formData.append("file", fileList.value[fileList.value.length - 1].raw);
importTableData.value = await importPetitionComplaint(formData);
step.value = 2;
nextTick(() => {
tableRef.value.toggleAllSelection();
});
}
const checkRowSize = computed(
() => tableRef.value?.getSelectionRows().length || 0
);
const tableRef = ref(null);
async function handleSaveImport() {
const rows = tableRef.value.getSelectionRows();
await addPetitionComplaint([...rows]);
feedback.msgSuccess(`成功导入${rows.length}条数据`);
show.value = false;
getList();
}
</script>
<style lang="scss" scoped>
</style>

0
src/views/data/PetitionComplaint.vue → src/views/data/PetitionComplaintExcel.vue

6
src/views/sensitivePerception/ClueData.vue

@ -102,17 +102,17 @@
const query = ref({});
const data = ref([
{
label: "123",
label: "全部",
value: 1,
children: [
{
label: "123",
label: "模型",
value: 3,
},
],
},
{
label: "123",
label: "执法监督",
value: 2,
},
]);

310
src/views/system/Depart.vue

@ -1,18 +1,7 @@
<template>
<div class="container">
<header>
<!-- <el-form>
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="请输入单位简称" >
<el-input placeholder="请输入单位简称" v-model="query.shortName" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-form> -->
<div class="mb-25 flex between">
<div class="mb-10">
<el-button
type="primary"
@click="handleAdd"
@ -21,75 +10,198 @@
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增单位</el-button
新增机构</el-button
>
<div>
<!-- <el-button type="primary" @click="getList">查询</el-button>
<el-button>重置</el-button> -->
</div>
</div>
</header>
<div class="table-container">
<el-table
:data="treeData"
row-key="id"
lazy
:load="load"
:expand-row-keys="['12630']"
>
<el-table-column label="单位简称" prop="shortName" />
<el-table-column
label="单位全称"
prop="name"
show-overflow-tooltip
/>
<el-table-column label="编码" prop="code" />
<el-table-column label="排序" prop="orderNo" width="80" />
<el-table-column label="最后更新时间" prop="updatedAt" width="200" />
<el-table-column label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag
v-if="row.status === Status.ENABLE"
type="success"
>启用</el-tag
<el-tabs v-model="activeName">
<el-tab-pane label="树" name="tree">
<div class="table-container">
<el-table :data="treeData" row-key="id" lazy :load="load">
<el-table-column label="机构简称" prop="shortName" />
<el-table-column
label="机构全称"
prop="name"
show-overflow-tooltip
/>
<el-table-column label="编码" prop="code" />
<el-table-column
label="排序"
prop="orderNo"
width="80"
/>
<el-table-column
label="最后更新时间"
prop="updatedAt"
width="200"
/>
<el-table-column
label="状态"
width="100"
align="center"
>
<el-tag v-else type="error" effect="dark">禁用</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['depart:add']"
>编辑</el-button
>
<el-button
type="danger"
link
@click="handleDel(row.id)"
v-perms="['depart:add']"
>删除</el-button
<template #default="{ row }">
<el-tag
v-if="row.status === Status.ENABLE"
type="success"
>启用</el-tag
>
<el-tag v-else type="danger" effect="dark"
>禁用</el-tag
>
</template>
</el-table-column>
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['depart:add']"
>编辑</el-button
>
<el-button
type="danger"
link
@click="handleDel(row)"
v-perms="['depart:add']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</el-tab-pane>
<el-tab-pane label="列表" name="list">
<header class="mb-20">
<el-form>
<el-form :label-width="114">
<el-row>
<el-col :span="6">
<el-form-item label="机构简称">
<el-input
placeholder="请输入机构简称"
v-model="query.shortName"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="机构全称">
<el-input
placeholder="请输入机构全称"
v-model="query.name"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="机构编码">
<el-input
placeholder="请输入机构编码"
v-model="query.code"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="6">
<div class="flex end">
<el-button
type="primary"
@click="getList"
>查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
</el-form>
</header>
<div class="table-container">
<el-table :data="list" row-key="id" :load="load">
<el-table-column label="机构简称" prop="shortName" />
<el-table-column
label="机构全称"
prop="name"
show-overflow-tooltip
/>
<el-table-column label="编码" prop="code" />
<el-table-column
label="排序"
prop="orderNo"
width="80"
/>
<el-table-column
label="最后更新时间"
prop="updatedAt"
width="200"
/>
<el-table-column
label="状态"
width="100"
align="center"
>
</template>
</el-table-column>
</el-table>
</div>
<template #default="{ row }">
<el-tag
v-if="row.status === Status.ENABLE"
type="success"
>启用</el-tag
>
<el-tag v-else type="danger" effect="dark"
>禁用</el-tag
>
</template>
</el-table-column>
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['depart:add']"
>编辑</el-button
>
<el-button
type="danger"
link
@click="handleDel(row)"
v-perms="['depart:add']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
v-model:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
>
</el-pagination>
</div>
</el-tab-pane>
</el-tabs>
</div>
<el-dialog
:title="mode === 'add' ? '新增单位' : '编辑单位'"
:title="mode === 'add' ? '新增机构' : '编辑机构'"
v-model="show"
width="600"
>
<el-form :model="form" :label-width="120" ref="fomrRef">
<el-form-item
label="上级单位"
label="上级机构"
prop="pid"
:rules="{
required: true,
message: '请选择上级单位',
message: '请选择上级机构',
trigger: ['change'],
}"
v-if="form.id !== '12630'"
@ -97,45 +209,45 @@
<depart-tree-select v-model="form.pid" />
</el-form-item>
<el-form-item
label="单位全称"
label="机构全称"
prop="name"
:rules="{
required: true,
message: '请输入单位全称',
message: '请输入机构全称',
trigger: ['blur'],
}"
>
<el-input placeholder="请输入" v-model="form.name" />
</el-form-item>
<el-form-item
label="单位简称"
label="机构简称"
prop="shortName"
:rules="{
required: true,
message: '请输入单位简称',
message: '请输入机构简称',
trigger: ['blur'],
}"
>
<el-input placeholder="请输入" v-model="form.shortName" />
</el-form-item>
<el-form-item
label="单位编码"
label="机构编码"
prop="code"
:rules="{
required: true,
message: '请输入单位编码',
message: '请输入机构编码',
trigger: ['blur'],
}"
>
<el-input placeholder="单位编码 430" v-model="form.code" />
<el-input placeholder="机构编码 430" v-model="form.code" />
</el-form-item>
<el-form-item label="排序" prop="orderNo">
<el-input
placeholder="单位排序号,数字越小越靠前"
placeholder="机构排序号,数字越小越靠前"
v-model="form.orderNo"
type="number"
/>
<p>单位排序号数字越小越靠前</p>
<p>机构排序号数字越小越靠前</p>
</el-form-item>
<el-form-item
label="状态"
@ -164,23 +276,48 @@
</template>
<script setup>
import { Status } from "@/enums/appEnums";
import { departTreeList, addDepart, updateDepart } from "@/api/system/depart";
import { onMounted } from "vue";
import {
departTreeList,
addDepart,
updateDepart,
delDepart,
listDepart,
} from "@/api/system/depart";
import feedback from "@/utils/feedback";
const treeData = ref([]);
const activeName = ref("tree");
const query = ref({})
function getList() {
departTreeList({
const query = ref({
size: 10,
current: 1,
});
}).then((data) => {
function getTree() {
departTreeList({}).then((data) => {
treeData.value = data;
treeData.value[0].hasChildren = false
});
}
const list = ref([]);
const total = ref(0);
function getList() {
listDepart(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
});
}
function reset() {
query.value = {
current: 1,
size: 10,
};
getList();
}
onMounted(() => {
getTree();
getList();
});
@ -209,14 +346,16 @@ function handleAdd() {
function handleEdit(row) {
show.value = true;
form.value = row;
form.value = { ...row };
mode.value = "edit";
}
async function handleDel(id) {
await feedback.confirm("确定要删除该单位?");
await delMenu(id);
async function handleDel(row) {
await feedback.confirm(`确定要删除 ${row.shortName}`);
await delDepart(row.id);
feedback.msgSuccess("删除成功");
getTree();
getList();
}
async function submit() {
@ -230,6 +369,7 @@ async function submit() {
await updateDepart(form.value);
}
show.value = false;
getTree();
getList();
feedback.msgSuccess("操作成功");
}

3
src/views/system/Dict.vue

@ -396,6 +396,9 @@ async function handleDelDictData(dictCode) {
getDatas();
}
const tableRef = ref(null)
</script>
<style lang="scss" scoped>
</style>

85
src/views/system/Holiday.vue

@ -2,20 +2,42 @@
<div class="container">
<header>
<el-form :label-width="120">
<el-form-item label="年份"></el-form-item>
<el-form-item label="年份">
<el-date-picker
v-model="year"
type="year"
value-format="YYYY"
placeholder="请选择年份"
:disabled-date="disabledDate"
/>
</el-form-item>
</el-form>
</header>
<div>
<el-row :gutter="20">
<el-col :span="8" v-for="month in months" :key="month">
<el-col :span="8" v-for="item in holidays" :key="item.month">
<div class="calendar-month">
<header>{{ year }}{{ month }}</header>
<header>{{ year }}{{ item.month }}</header>
<div class="calendar-week flex wrap">
<div class="calendar-cell calendar-cell_week flex center" v-for="week in weeks" :key="week">
<div
class="calendar-cell calendar-cell_week flex center"
v-for="week in weeks"
:key="week"
>
<div class="cell">{{ week }}</div>
</div>
<div class="calendar-cell flex center" v-for="(item, index) in getMonthDays(month)" :key="index">
<div class="cell">{{ item.day }}</div>
<div
class="calendar-cell flex center calendar-body"
v-for="(day, index) in item.days"
:key="index"
>
<div
class="cell"
:disabled="!day.day"
:isHoliday="day.flag"
>
{{ day.day }}
</div>
</div>
</div>
</div>
@ -25,31 +47,31 @@
</div>
</template>
<script setup>
import moment from 'moment'
import moment from "moment";
import { listHolidays } from "@/api/system/holiday";
const year = ref(2024);
const holiday = ref([]);
const year = ref(moment().year() + '');
const holidays = ref([]);
const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const weeks = ["一", "二", "三", "四", "五", "六", "日"];
function getMonthDays(month) {
const days = [];
const beginDay = moment([year.value, month - 1]).startOf('month');
const beginDayOfWeek = beginDay.day();
const endDay = moment([year.value, month - 1]).endOf('month');
// const endDayOfWeek = endDay.day();
for (let i = 0; i < beginDayOfWeek ? beginDayOfWeek - 1 : 6; i++) {
days.push({})
}
for (let i = 1; i <= endDay.date(); i++) {
days.push({
day: i,
flag: false
})
}
return days;
const disabledDate = (time) => {
return time.getFullYear() < 2023
}
function getHolidays() {
listHolidays(year.value).then((data) => {
holidays.value = data;
});
}
onMounted(() => {
getHolidays();
})
watch(year, () => {
getHolidays();
})
</script>
<style lang="scss" scoped>
.calendar-month {
@ -74,10 +96,19 @@ function getMonthDays(month) {
height: 36px;
line-height: 36px;
border-radius: 50%;
&:hover {
}
&.calendar-body {
.cell[disabled="false"]:hover {
background-color: #eee;
cursor: pointer;
}
.cell[isHoliday="true"] {
background-color: #ff5722;
color: #fff;
&:hover {
background-color: #f9825d;
}
}
}
&.calendar-cell_week {
color: #777;

179
src/views/system/Police.vue

@ -47,9 +47,15 @@
<el-form-item label="所属单位">
<div class="flex gap v-center" style="width: 100%">
<div style="width: 220px">
<depart-tree-select v-model="query.departId" />
<depart-tree-select
v-model="query.departId"
/>
</div>
<el-checkbox v-model="query.departBranch" label="当前单位及所有子单位" size="large" />
<el-checkbox
v-model="query.departBranch"
label="当前单位及所有子单位"
size="large"
/>
</div>
</el-form-item>
</el-col>
@ -81,16 +87,71 @@
</header>
<div class="table-container" v-loading="loading">
<el-table :data="polices" row-key="id">
<el-table-column type="expand">
<template #default="{ row }">
<div class="row mt-10">
<div class="col col-6">
<label>年龄</label>
<span>{{ getAge(row.idCode) }}</span>
</div>
<div class="col col-6">
<label>婚姻状况</label>
<span>{{ getDictLable(dict.maritalStatus, row.maritalStatus) }}</span>
</div>
<div class="col col-6">
<label>子女</label>
<span>{{ row.personType }}</span>
</div>
<div class="col col-6">
<label>学历</label>
<span>{{ getDictLable(dict.education, row.education) || '/' }}</span>
</div>
</div>
<div class="row mt-10">
<div class="col col-6">
<label>创建时间</label>
<span>{{ row.createdAt }}</span>
</div>
<div class="col col-6">
<label>更新时间</label>
<span>{{ row.updatedAt }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="姓名" prop="name" width="100" />
<el-table-column label="警号" prop="empNo" width="100" show-overflow-tooltip />
<el-table-column label="所属单位" prop="departName" show-overflow-tooltip />
<el-table-column label="所属单位简称" prop="departShortName" show-overflow-tooltip />
<el-table-column
label="警号"
prop="empNo"
width="100"
show-overflow-tooltip
/>
<el-table-column
label="所属机构"
show-overflow-tooltip
>
<template #default="{ row }">
<span class="mr-4">{{ row.parentDepartShortName }}</span>
<span>{{ row.departShortName }}</span>
</template>
</el-table-column>
<el-table-column label="职位" prop="position" width="120" />
<el-table-column label="人员属性" prop="job" width="120" />
<el-table-column label="身份证" prop="idCode" width="200" />
<el-table-column label="电话" prop="mobile" width="200" />
<el-table-column label="电话" prop="mobile" width="180" />
<el-table-column label="人员属性" width="160" align="center">
<template #default="{ row }">
<span>{{ getDictLable(dict.personType, row.personType) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)" v-perms="['police:add']"
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['police:add']"
>编辑</el-button
>
<el-button
@ -126,23 +187,16 @@
width="800"
:lock-scroll="false"
>
<el-form :label-width="120">
<el-form-item label="数据单位">
<el-form :label-width="160">
<el-form-item label="机构权限">
<depart-tree-select
v-model="authForm.departs"
multiple
check-strictly
/>
</el-form-item>
<el-form-item label="业务权限">
<el-select v-model="authForm.sources" multiple>
<el-option
v-for="item in dict.problemSources"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
<el-form-item label="业务权限(问题来源)">
<el-tree-select :data="dictProblemSources" :props="{value: 'id'}" node-key="id" clearable filterable v-model="authForm.sources" multiple />
</el-form-item>
</el-form>
<footer class="flex end">
@ -157,6 +211,14 @@
width="600"
>
<el-form :model="form" :label-width="120" ref="fomrRef">
<el-form-item label="头像" prop="avatarUrl">
<el-avatar
shape="square"
:size="50"
:src="form.avatarUrl"
:icon="UserFilled"
/>
</el-form-item>
<el-form-item
label="姓名"
prop="name"
@ -179,6 +241,16 @@
>
<el-input placeholder="请输入" v-model="form.empNo" />
</el-form-item>
<el-form-item
label="身份证"
prop="idCode"
:rules="{
required: true,
message: '请输入身份证',
}"
>
<el-input placeholder="请输入" v-model="form.idCode" />
</el-form-item>
<el-form-item
label="所属单位"
prop="orgId"
@ -190,24 +262,51 @@
>
<depart-tree-select v-model="form.orgId" />
</el-form-item>
<el-form-item
label="职位"
prop="position"
>
<el-form-item label="职位" prop="position">
<el-select v-model="form.position" clearable>
<el-option value="正职">正职</el-option>
<el-option value="副职">副职</el-option>
</el-select>
</el-form-item>
<el-form-item label="身份证" prop="idCode" :rules="{
required: true,
message: '请输入身份证'
}">
<el-input placeholder="请输入" v-model="form.idCode" />
</el-form-item>
<el-form-item label="电话" prop="mobile">
<el-input placeholder="请输入" v-model="form.mobile" />
</el-form-item>
<el-form-item label="人员属性">
<el-radio-group v-model="form.personType">
<el-radio
v-for="item in dict.personType"
:key="item.dictCode"
:value="item.dictValue"
>{{ item.dictLabel }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item label="婚姻状况">
<el-radio-group v-model="form.maritalStatus">
<el-radio
v-for="item in dict.maritalStatus"
:key="item.dictCode"
:value="item.dictValue"
>{{ item.dictLabel }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item label="子女">
<el-radio-group v-model="form.personType">
<el-radio value="无子女"></el-radio>
<el-radio value="有子女"></el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="学历">
<el-select v-model="form.education">
<el-option
v-for="item in dict.education"
:key="item.dictCode"
:value="item.dictValue"
:label="item.dictLabel"
/>
</el-select>
</el-form-item> -->
</el-form>
<footer class="flex end">
<el-button @click="show = false">取消</el-button>
@ -221,12 +320,22 @@ import {
getPoliceAuths,
addPolice,
updatePolice,
updatePoliceAuths
updatePoliceAuths,
} from "@/api/system/police";
import useCatchStore from "@/stores/modules/catch";
import feedback from "@/utils/feedback";
import { getDictLable } from "@/utils/util";
import { UserFilled } from "@element-plus/icons-vue";
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"problemSources",
"personType",
"education",
"maritalStatus"
]);
const dict = useCatchStore().getDicts(["problemSources"]);
const dictProblemSources = catchStore.getDictProblemSources();
const polices = ref([]);
const query = ref({
@ -258,7 +367,7 @@ function reset() {
const authShow = ref(false);
const authForm = ref({});
let activeIdCode = '';
let activeIdCode = "";
function handleEditAuth(row) {
getPoliceAuths(row.idCode).then((data) => {
activeIdCode = row.idCode;
@ -271,7 +380,7 @@ function authSubmit() {
updatePoliceAuths(activeIdCode, authForm.value).then(() => {
authShow.value = false;
feedback.msgSuccess("操作成功");
})
});
}
const mode = ref("add");
@ -306,6 +415,12 @@ async function submit() {
getList();
}
function getAge(idCode) {
if (!idCode || idCode.length !== 18) {
return "";
}
return new Date().getFullYear() - parseInt(idCode.substr(6, 4));
}
</script>
<style lang="scss" scoped>
</style>

141
src/views/work/NegativeTask.vue

@ -0,0 +1,141 @@
<template>
<div class="container">
<header>
<el-form :label-width="120">
<el-row>
<el-col :span="6">
<el-form-item label="任务名称">
<el-input
placeholder="请输入"
v-model="query.taskName"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="创建时间">
<el-date-picker
v-model="query.crtTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
format="YYYY-MM-DD HH:mm:ss"
range-separator="~"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="flex end mb-20">
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column label="任务名称" prop="taskName" show-overflow-tooltip />
<el-table-column
label="导出条数"
prop="importRow"
align="center"
/>
<el-table-column label="创建时间" prop="crtTime" />
<el-table-column label="更新时间" prop="updTime" />
<el-table-column label="操作人" prop="crtUser" />
<el-table-column label="状态" prop="status">
<template #default="{ row }">
<el-tag type="success" v-if="row.status === '0'"
>导出成功</el-tag
>
<el-tag type="danger" v-else-if="row.status === '1'"
>导出失败</el-tag
>
<el-tag type="primary" v-else>导出中</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
link
@click="handleDownload(row)"
>下载</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex end mt-8">
<el-pagination
@size-change="getList"
@current-change="getList"
:current-page="query.current"
:page-sizes="[10, 20, 50]"
:page-size="query.size"
v-model:current-page="query.current"
layout="total, sizes, prev, pager, next"
:total="total"
>
</el-pagination>
</div>
</div>
</template>
<script setup>
import { BASE_PATH } from "@/api/request";
import { listNegativeTask } from "@/api/work/negativeTask";
const list = ref([]);
const query = ref({
size: 10,
current: 1,
});
const total = ref(0);
function getList() {
listNegativeTask(query.value).then((data) => {
list.value = data.records;
total.value = data.total;
});
}
function reset() {
query.value = {
size: 10,
current: 1,
};
getList();
}
onMounted(() => {
getList();
});
function handleDownload(row) {
fetch(`${BASE_PATH}/file/stream${row.filePath}`)
.then((response) => {
console.log(response);
return response.blob();
})
.then((res) => {
console.log(res);
const blob = new Blob([res], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", row.taskName + ".xlsx");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
});
}
</script>
<style lang="scss" scoped>
</style>

73
src/views/work/Query.vue

@ -110,10 +110,17 @@
<div class="form-row flex v-center">
<label class="text-center">其他选项</label>
<div class="flex gap-20">
<el-tree-select :data="dictProblemSources" :props="{value: 'id'}" node-key="id" v-model="query.problemSourcesCode" clearable filterable size="small"
style="width: 146px"
placeholder="问题来源" />
<el-tree-select
:data="dictProblemSources"
:props="{ value: 'id' }"
node-key="id"
v-model="query.problemSourcesCode"
clearable
filterable
size="small"
style="width: 180px"
placeholder="问题来源"
/>
<el-select
size="small"
@ -199,8 +206,12 @@
</div>
</div>
</el-form>
<div class="flex end mt-20 mb-26">
<el-button type="primary">数据导出</el-button>
<div class="flex between mt-20 mb-26">
<el-button
type="primary"
@click="handleExport"
>数据导出</el-button
>
<div>
<el-button type="primary" @click="getList">
<template #icon
@ -318,17 +329,36 @@
>
</template>
</el-table-column> -->
<el-table-column label="流程限时" width="150" align="center">
<el-table-column
label="流程限时"
width="150"
align="center"
>
<template #default="{ row }">
<countdown
:time="row.remainingDuration"
v-if="row.remainingDuration &&
v-if="
row.remainingDuration &&
row.processingStatus !==
ProcessingStatus.COMPLETED
ProcessingStatus.COMPLETED
"
/>
<el-tag v-else-if="row.handleTimeout" type="error" effect="dark">办理超时 {{ formatTimeText(row.handleTimeout) }}</el-tag>
<el-tag v-else-if="row.processingStatus === ProcessingStatus.COMPLETED" type="success" effect="dark">未超时</el-tag>
<el-tag
v-else-if="row.handleTimeout"
type="danger"
effect="dark"
>办理超时
{{ formatTimeText(row.handleTimeout) }}</el-tag
>
<el-tag
v-else-if="
row.processingStatus ===
ProcessingStatus.COMPLETED
"
type="success"
effect="dark"
>未超时</el-tag
>
</template>
</el-table-column>
<el-table-column label="办理状态" width="110">
@ -338,7 +368,7 @@
row.processingStatus ===
ProcessingStatus.COMPLETED
? 'success'
: ''
: 'primary'
"
v-if="row.processingStatus"
>{{
@ -386,9 +416,10 @@
/>
</template>
<script setup>
import moment from "moment";
import { listNegative } from "@/api/work/negative";
import { ElLoading } from 'element-plus'
import { listNegative, negativeExport } from "@/api/work/negative";
import { getDictLable, formatTimeText } from "@/utils/util";
import feedback from "@/utils/feedback";
import { ProcessingStatus } from "@/enums/flowEnums";
import useCatchStore from "@/stores/modules/catch";
@ -444,6 +475,20 @@ function handleAction(row) {
show.value = true;
activeNegativeId.value = row.id;
}
const router = useRouter()
async function handleExport() {
await feedback.confirm("请确定导出当前页面所有数据");
const loading = ElLoading.service({
lock: true,
text: "导出中...",
background: "rgba(0, 0, 0, 0.5)",
});
await negativeExport(query.value);
loading.close()
await feedback.confirm("导出任务已生成,请到“导出记录”页面查看");
router.push('/negative/export')
}
</script>
<style lang="scss" scoped>
.form-row {

2
src/views/work/Todo.vue

@ -95,7 +95,7 @@
v-perms="['negative:add']"
><template #icon>
<icon name="el-icon-Plus" /> </template
>问题录入</el-button
>问题下发</el-button
>
</div>
<div>

3
vite.config.ts

@ -78,7 +78,8 @@ export default ({ mode }) => {
}
},
build: {
outDir: 'v2'
outDir: 'v2',
target: "es2015"
}
})
}

Loading…
Cancel
Save