Browse Source

fit: 预警线索页面。fit: 任务分发页面

main
wxc 1 year ago
parent
commit
6e91320c07
  1. 23
      src/api/sensitivePerception/model.ts
  2. 14
      src/api/sensitivePerception/modelClue.ts
  3. 6
      src/api/system/dict.ts
  4. 6
      src/api/system/police.ts
  5. 23
      src/components/depart-tree-select.vue
  6. 4
      src/components/model-icon-picker.vue
  7. 92
      src/components/model-tree.vue
  8. 7
      src/enums/appEnums.ts
  9. 13
      src/enums/dictEnums.ts
  10. 4
      src/layout/components/Header.vue
  11. 1
      src/permission.ts
  12. 4
      src/router/routes.ts
  13. 4
      src/views/Login.vue
  14. 275
      src/views/sensitivePerception/Model.vue
  15. 104
      src/views/sensitivePerception/ModelClue.vue
  16. 109
      src/views/sensitivePerception/ModelClueTask.vue
  17. 15
      src/views/system/Dict.vue
  18. 3
      src/views/system/Holiday.vue
  19. 4
      src/views/system/Menu.vue
  20. 95
      src/views/system/Police.vue
  21. 139
      src/views/system/Role.vue
  22. 92
      src/views/system/User.vue
  23. 10
      vite.config.ts

23
src/api/sensitivePerception/model.ts

@ -2,14 +2,33 @@ import request from "@/api/request";
export function listModel(query) {
return request.get({
url: '/model',
url: '/models',
query
});
}
export function treeModel() {
return request.get({
url: '/models/tree'
});
}
export function addModel(body) {
return request.post({
url: '/model',
url: '/models',
body
});
}
export function updateModel(body) {
return request.put({
url: '/models',
body
});
}
export function delModel(id) {
return request.del({
url: `/models/${id}`
});
}

14
src/api/sensitivePerception/modelClue.ts

@ -0,0 +1,14 @@
import request from "@/api/request";
export function listModelClue(query) {
return request.get({
url: `/model/clues`,
query
});
}
export function listTopModelClueRecords(modelId) {
return request.get({
url: `/model/clue/records/${modelId}/top`
});
}

6
src/api/system/dict.ts

@ -21,6 +21,12 @@ export function updateDictType(body) {
});
}
export function delDictType(id) {
return request.del({
url: '/dict/' + id
});
}
export function listDictDatas(query, dictType) {
return request.get({
url: `/dict/${dictType}/dictData`,

6
src/api/system/police.ts

@ -21,6 +21,12 @@ export function updatePolice(body) {
});
}
export function delPolice(id) {
return request.del({
url: `/police/${id}`
});
}
export function listPoliceAll(departId) {
return request.get({
url: `/police/${departId}/all`

23
src/components/depart-tree-select.vue

@ -1,11 +1,32 @@
<template>
<el-tree-select :data="departs" :props="{label: 'shortName', value: 'id'}" node-key="id" :default-expanded-keys="['12630']" clearable filterable check-strictly />
<el-tree-select :data="data" :props="{label: 'shortName', value: 'id'}" node-key="id" :default-expanded-keys="['12630']" clearable filterable check-strictly />
</template>
<script setup>
import useCatchStore from '@/stores/modules/catch'
import { ROOT_DEPART_ID } from '@/enums/appEnums';
const data = ref([])
const departs = useCatchStore().getDeparts();
const props = defineProps({
showRoot: {
type: Boolean,
default: false
}
})
onMounted(() => {
getData()
})
watch(departs, () => {
getData()
})
function getData() {
if (!props.showRoot && departs.length && departs[0].id === ROOT_DEPART_ID) {
data.value = departs[0].children
} else {
data.value = departs
}
}
</script>
<style lang="scss" scoped>

4
src/components/model-icon-picker.vue

@ -7,7 +7,7 @@
</template>
<script setup>
defineProps({
const props= defineProps({
modelValue: {
type: String,
}
@ -17,7 +17,7 @@ const emit = defineEmits(['update:modelValue'])
const icons = ['local-icon-ic_01', 'local-icon-ic_02', 'local-icon-ic_03', 'local-icon-ic_04', 'local-icon-ic_05', 'local-icon-ic_06']
const active = ref('')
const active = ref(props.modelValue)
function handleClick(item) {
active.value = item

92
src/components/model-tree.vue

@ -0,0 +1,92 @@
<template>
<el-input v-model="filterText" placeholder="搜索" class="mb-10">
<template #prefix>
<el-icon class="el-input__icon"><search /></el-icon>
</template>
</el-input>
<el-tree
:data="treeData"
node-key="id"
:render-content="renderContent"
:default-expanded-keys="[0]"
:filter-node-method="filterNode"
ref="treeRef"
/>
</template>
<script lang="ts" setup>
import Icon from "@/components/icon/index.vue";
import { treeModel } from "@/api/sensitivePerception/model";
const treeData = ref([
{
label: "全部",
id: 0,
type: "modelClass",
children: [],
},
]);
const list = ref([]);
const total = ref(0)
onMounted(() => {
treeModel().then((data) => {
treeData.value[0].children = data;
getList()
});
});
function renderContent(
h,
{
node,
data,
store,
}: {
node: Node;
data: Tree;
store: Node["store"];
}
) {
console.log(node);
return h(
"div",
{
class: "flex v-center",
},
h(
Icon,
{
name:
node.data.type === "modelClass"
? "el-icon-Folder"
: "el-icon-Cpu",
class: "mr-8",
},
node.label
),
h("span", null, node.label)
);
}
const filterText = ref('')
const treeRef = ref(null)
const filterNode = (value: string, data: Tree) => {
if (!value) return true
return data.label.includes(value)
}
watch(filterText, (val) => {
treeRef.value!.filter(val)
})
</script>
<style lang="scss" scoped>
:deep() {
.el-tree-node.is-current {
& > .el-tree-node__content {
background: #e1e5ff;
}
}
}
</style>

7
src/enums/appEnums.ts

@ -9,8 +9,13 @@ export const MENU_ROOT_ID = 0;
export const DICT_CONTENT_ROOT_ID = -1;
// 部门跟节点
export const ROOT_DEPART_ID = '12630';
// 状态
export enum Status {
ENABLE = '1',
DISABLE = '0'
}
}
export const WEEKS = ["一", "二", "三", "四", "五", "六", "日"];

13
src/enums/dictEnums.ts

@ -108,8 +108,15 @@ export enum SubjectiveAspect {
OTHER = '3'
}
// 分发周期
// 分发方式
export enum DistributionMethod {
AUTO = '1',
MANUAL = '2'
NEGATIVE_DISTRIBUTE = '1',
DATA_SAVE = '2',
WARNING_NOTIFICATION = '3'
}
// 分发周期
export enum DistributionCycle {
DAY = 'day',
WEEKLY = 'weekly'
}

4
src/layout/components/Header.vue

@ -16,10 +16,10 @@
</section>
</header>
<ul class="userinfo-dropdown" v-if="dropdownShow">
<!-- <li class="flex gap v-center" @click="openHelp">
<li class="flex gap v-center" @click="openHelp">
<icon name="local-icon-question" :size="22" />
<span>帮助手册</span>
</li> -->
</li>
<li class="flex gap v-center" @click="supportShow = true">
<icon name="el-icon-Star" :size="22" />
<span>技术支持</span>

1
src/permission.ts

@ -45,7 +45,6 @@ router.beforeEach(async (to, from, next) => {
}
router.addRoute(route)
})
console.log(routes)
next({ ...to, replace: true })
return
}

4
src/router/routes.ts

@ -6,6 +6,10 @@ import Layout from '@/layout/Index.vue'
export const LAYOUT = () => Promise.resolve(Layout)
export const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/login',
component: () => import('@/views/Login.vue'),

4
src/views/Login.vue

@ -18,7 +18,7 @@
<el-form-item prop="account">
<el-input
v-model.trim="formData.account"
placeholder="请输入号"
placeholder="请输入身份证/警号"
size="large"
@input="errMsg = ''"
style="--el-input-height: 50px"
@ -71,7 +71,7 @@ const rules = {
account: [
{
required: true,
message: "请输入号",
message: "请输入身份证/警号",
trigger: ["blur", "change"],
},
],

275
src/views/sensitivePerception/Model.vue

@ -1,4 +1,5 @@
<template>
<div class="container">
<el-row :gutter="20">
<el-col :span="4">
@ -45,7 +46,7 @@
</el-row>
</el-form>
<div class="flex between mb-20">
<el-button type="primary" @click="show = true"
<el-button type="primary" @click="handleAdd"
>添加模型</el-button
>
<div>
@ -95,19 +96,7 @@
)
}}</span>
</div>
<div
class="col col-12"
v-if="
item.windingNumber
"
>
<label>下发条数</label>
<span
>{{
item.windingNumber
}}</span
>
</div>
</div>
<div class="col">
<label>最近活跃时间</label>
@ -142,8 +131,29 @@
</el-row>
</div>
<el-dialog title="添加模型" v-model="show" top="5vh">
<el-dialog
:title="mode === 'add' ? '添加模型' : '编辑模型'"
v-model="show"
top="5vh"
>
<el-form label-width="120" ref="formRef" :model="form">
<el-form-item
label="模型类型"
prop="classId"
:rules="{
required: true,
message: '请选择模型类型',
}"
>
<el-select v-model="form.classId" style="width: 340px">
<el-option
v-for="item in classes"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="模型名称"
prop="modelName"
@ -159,20 +169,21 @@
v-model="form.modelName"
/>
</el-form-item>
<el-form-item
label="模型类型"
prop="classId"
label="建模方式"
prop="modelingMethod"
:rules="{
required: true,
message: '请选择模型类型',
message: '请选择建模方式',
}"
>
<el-select v-model="form.classId" style="width: 340px">
<el-select v-model="form.modelingMethod" style="width: 340px">
<el-option
v-for="item in classes"
:key="item.id"
:label="item.name"
:value="item.id"
v-for="item in dict.modelingMethod"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
@ -186,6 +197,24 @@
>
<model-icon-picker v-model="form.icon" />
</el-form-item>
<el-form-item
label="数据类型"
prop="modelDataType"
:rules="{
required: true,
message: '请选择数据类型',
}"
>
<el-radio-group v-model="form.modelDataType" class="block">
<el-radio
v-for="item in dict.modelDataType"
:key="item.dictCode"
:value="item.dictValue"
>{{ item.dictLabel
}}{{ item.remark ? `(${item.remark})` : "" }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item
label="分发方式"
prop="distributionMethod"
@ -204,8 +233,18 @@
>
</el-radio-group>
</el-form-item>
<template v-if="form.distributionMethod === DistributionMethod.AUTO">
<el-form-item label="分发周期" prop="distributionCycle">
<template
v-if="form.distributionMethod === DistributionMethod.NEGATIVE_DISTRIBUTE"
>
<el-form-item
label="分发周期"
prop="distributionCycle"
:rules="{
required: true,
message: '请选择分发周期',
}"
>
<el-radio-group
v-model="form.distributionCycle"
class="block"
@ -220,6 +259,33 @@
}}</el-radio
>
</el-radio-group>
<div class="flex ml-20" v-if="form.distributionCycle">
<el-form-item
label="周"
prop=""
label-width="80"
:rules="{
required: true,
message: '请选择',
}"
v-if="form.distributionCycle === DistributionCycle.WEEKLY"
>
<el-select style="width: 120px" clearable>
<el-option v-for="(item, index) in WEEKS" :key="index" :label="`周${item}`" :value="index" />
</el-select>
</el-form-item>
<el-form-item
label="时间"
prop="distributionCycleTime"
label-width="80"
:rules="{
required: true,
message: '请选择',
}"
>
<el-time-picker v-model="form.distributionCycleTime" placeholder="请选择" style="width: 120px" value-format="HH:mm:ss" clearable />
</el-form-item>
</div>
</el-form-item>
<el-form-item
label="办理时限"
@ -308,9 +374,9 @@
</el-form>
<footer class="flex end">
<el-button @click="show = false" size="large">取消</el-button>
<el-button type="primary" size="large" @click="handleSubmit"
>添加模型</el-button
>
<el-button type="primary" size="large" @click="handleSubmit">{{
mode === "add" ? "添加模型" : "确认"
}}</el-button>
</footer>
</el-dialog>
@ -331,6 +397,15 @@
</div>
</div>
<div class="row">
<div class="col col-8">
<label>建模方式</label>
<span>{{
getDictLable(
dict.modelingMethod,
activeModel.modelingMethod
)
}}</span>
</div>
<div class="col col-8">
<label>分发方式</label>
<span>{{
@ -340,6 +415,15 @@
)
}}</span>
</div>
<div class="col col-8">
<label>数据类型</label>
<span>{{
getDictLable(
dict.modelDataType,
activeModel.modelDataType
)
}}</span>
</div>
<div class="col col-8">
<label>分发周期</label>
<span>{{
@ -385,10 +469,7 @@
<label>最近活跃时间</label>
<span>{{ activeModel.updateTime }}</span>
</div>
<div class="col col-8">
<label>下发条数</label>
<span>{{ activeModel.windingNumber }}</span>
</div>
</div>
<div class="row mb-20">
<div class="col col-24">
@ -396,38 +477,48 @@
<span>{{ activeModel.remarks }}</span>
</div>
</div>
<div class="flex end mb-20">
<el-button type="primary">查看预警线索</el-button>
<el-button type="primary">预警模型设计</el-button>
</div>
<div class="flex end mb-20"></div>
</el-col>
</el-row>
<div>
<div class="mb-10">
<h4 style="margin: 10px 0" class="text-primary">预警记录</h4>
<el-table :data="tableData" size="small">
<el-table-column label="同步时间" prop="time" />
<el-table-column label="预警条数" prop="number" />
<el-table-column label="分发状态" prop="state" />
</el-table>
<div style="min-height: 300px">
<div class="table-container">
<el-table :data="tableData" size="small">
<el-table-column label="同步时间" prop="createTime" />
<el-table-column label="预警条数" prop="size" />
<el-table-column label="分发状态" prop="state" />
</el-table>
</div>
</div>
</div>
<footer class="flex end">
<el-button @click="show = false" type="primary" plain size="large"
<el-button @click="handleEdit" type="primary" plain size="large"
>编辑模型</el-button
>
<el-button type="danger" plain @click="submit" size="large"
<el-button type="danger" plain @click="handleDel" size="large"
>删除模型</el-button
>
</footer>
</el-dialog>
</template>
<script setup>
import { DistributionMethod } from '@/enums/dictEnums'
import { DistributionMethod, DistributionCycle } from "@/enums/dictEnums";
import { WEEKS } from "@/enums/appEnums";
import { listModelClass } from "@/api/sensitivePerception/modelClass";
import { addModel, listModel } from "@/api/sensitivePerception/model";
import {
addModel,
updateModel,
delModel,
listModel,
} from "@/api/sensitivePerception/model";
import { listTopModelClueRecords } from "@/api/sensitivePerception/modelClue";
import useCatchStore from "@/stores/modules/catch";
import { getDictLable } from "@/utils/util";
import feedback from "@/utils/feedback";
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"distributionMethod",
@ -435,6 +526,8 @@ const dict = catchStore.getDicts([
"distributionFlow",
"timeLimit",
"approvalFlow",
"modelingMethod",
"modelDataType",
]);
const query = ref({
@ -473,69 +566,65 @@ function handleChangeClass(id) {
}
const show = ref(false);
const mode = ref("add");
const form = ref({
distributionMethod: "1",
});
watch(mode, (val) => {
if (val === "add") {
initForm();
}
});
function initForm() {
form.value = { distributionMethod: "1" };
}
const formRef = ref(null);
function handleAdd() {
show.value = true;
mode.value = "add";
}
function handleEdit() {
show.value = true;
mode.value = "edit";
form.value = { ...activeModel.value };
}
async function handleSubmit() {
await formRef.value.validate();
await addModel(form.value);
if (mode.value === "add") {
await addModel(form.value);
} else {
activeModel.value = await updateModel(form.value);
}
getList();
form.value = { distributionMethod: "1" };
initForm();
show.value = false;
feedback.msgSuccess("模型添加成功");
feedback.msgSuccess("操作成功");
}
async function handleDel() {
await feedback.confirm("确定删除该模型?");
await delModel(activeModel.value.id);
feedback.msgSuccess("操作成功");
getList();
detailShow.value = false;
}
const detailShow = ref(false);
const activeModel = ref({});
const tableData = ref([
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
{
time: "2024-09-20 11:00:00",
number: 122,
state: "已分发",
},
]);
const tableData = ref([]);
function openDetail(item) {
detailShow.value = true;
async function openDetail(item) {
activeModel.value = item;
tableData.value = await listTopModelClueRecords(item.id);
detailShow.value = true;
}
</script>
<style lang="scss" scoped>
.menu {

104
src/views/sensitivePerception/ClueData.vue → src/views/sensitivePerception/ModelClue.vue

@ -1,8 +1,8 @@
<template>
<div class="container">
<el-row>
<el-row :gutter="20">
<el-col :span="4">
<el-tree :data="data" node-key="id" />
<model-tree />
</el-col>
<el-col :span="20">
<header>
@ -10,12 +10,9 @@
<el-row>
<el-col :span="8">
<el-form-item label="预警时间">
<date-time-range-picker-ext v-model="query.happenTime"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预警模型">
<el-input placeholder="请输入" />
<date-time-range-picker-ext
v-model="query.createTime"
/>
</el-form-item>
</el-col>
<el-col :span="8">
@ -27,23 +24,15 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="涉及人员">
<el-input placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="报警内容">
<el-input placeholder="请输入" />
<el-form-item label="预警内容">
<el-input placeholder="请输入" v-model="query.thingDesc" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="分发状态">
<el-select></el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="处理状态">
<el-select></el-select>
<el-select v-model="query.distributionState" clearable>
<el-option v-for="item in dict.distributionState" :label="item.dictLabel" :value="item.dictValue" />
</el-select>
</el-form-item>
</el-col>
</el-row>
@ -62,13 +51,16 @@
</header>
<div class="table-container">
<el-table :data="list">
<el-table-column label="预警时间" prop="" width="160" />
<el-table-column label="预警模型" prop="" width="120" />
<el-table-column label="涉及单位" prop="" width="120" />
<el-table-column label="预警内容" prop="" />
<el-table-column label="分发状态" prop="" />
<el-table-column label="处理状态" prop="" width="120" />
<el-table-column label="操作">
<el-table-column label="预警时间" prop="createTime" width="160" />
<el-table-column label="预警模型" prop="modelName" width="120" />
<el-table-column label="涉及单位" prop="involveDepartName" width="120" />
<el-table-column label="预警内容" prop="thingDesc" show-overflow-tooltip />
<el-table-column label="分发状态" align="center" width="120">
<template #default="{ row }">
<span>{{ getDictLable(dict.distributionState, row.distributionState) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template #default="{ row }">
<el-button
type="primary"
@ -76,12 +68,7 @@
@click="show = true"
>查看详情</el-button
>
<el-button
type="primary"
link
@click="show = true"
>处理详情</el-button
>
</template>
</el-table-column>
</el-table>
@ -90,26 +77,39 @@
</el-row>
</div>
</template>
<script setup>
const query = ref({});
const data = ref([
{
label: "全部",
value: 1,
children: [
{
label: "模型",
value: 3,
},
],
},
{
label: "执法监督",
value: 2,
},
<script lang="ts" setup>
import { listModelClue } from '@/api/sensitivePerception/modelClue'
import useCatchStore from "@/stores/modules/catch";
import { getDictLable } from "@/utils/util";
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"distributionState"
]);
const query = ref({});
const list = ref([]);
const total = ref(0)
onMounted(() => {
getList()
});
function getList() {
listModelClue(query.value).then(data => {
list.value = data.records
total.value = data.total
})
}
function reset() {
query.value = {}
getList()
}
</script>
<style scoped>
<style lang="scss" scoped>
</style>

109
src/views/sensitivePerception/ModelClueTask.vue

@ -0,0 +1,109 @@
<template>
<div class="container">
<el-row :gutter="20">
<el-col :span="4">
<model-tree />
</el-col>
<el-col :span="20">
<header>
<el-form :label-width="140">
<el-row>
<el-col :span="8">
<el-form-item label="预警时间">
<date-time-range-picker-ext
v-model="query.createTime"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="涉及单位">
<depart-tree-select
v-model="query.involveDepartId"
:check-strictly="false"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预警内容">
<el-input placeholder="请输入" v-model="query.thingDesc" clearable />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="分发状态">
<el-select v-model="query.distributionState" clearable>
<el-option v-for="item in dict.distributionState" :label="item.dictLabel" :value="item.dictValue" />
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="flex end mb-20">
<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="taskName" />
<el-table-column label="模型名称" prop="modelName" />
<el-table-column label="下发时间" prop="distributionTime" width="180" />
<el-table-column label="问题条数" prop="size" width="120" />
<el-table-column label="操作" width="180">
<template #default="{ row }">
<el-button
type="primary"
link
>查看详情</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
</el-row>
</div>
</template>
<script lang="ts" setup>
import { listModelClue } from '@/api/sensitivePerception/modelClue'
import useCatchStore from "@/stores/modules/catch";
import { getDictLable } from "@/utils/util";
const catchStore = useCatchStore();
const dict = catchStore.getDicts([
"distributionState"
]);
const query = ref({});
const list = ref([]);
const total = ref(0)
onMounted(() => {
getList()
});
function getList() {
listModelClue(query.value).then(data => {
list.value = data.records
total.value = data.total
})
}
function reset() {
query.value = {}
getList()
}
</script>
<style lang="scss" scoped>
</style>

15
src/views/system/Dict.vue

@ -254,6 +254,7 @@ import {
listDictTypes,
addDictType,
updateDictType,
delDictType,
listDictDatas,
addDictData,
updateDictData,
@ -310,6 +311,13 @@ const typeForm = ref({
status: "0",
});
const typeFormRef = ref(null);
watch(typeMode, (val) => {
if (val === "add") {
typeForm.value = { status: "0" };
}
});
const typeRules = {
dictName: [
{
@ -336,6 +344,13 @@ function handleEdit(row) {
typeForm.value = { ...row };
}
async function handleDel(row) {
await feedback.confirm(`确认删除字典 ${row.dictName}`)
await delDictType(row.dictId)
getList()
}
function submit() {
typeFormRef.value.validate((flag) => {
if (flag) {

3
src/views/system/Holiday.vue

@ -49,11 +49,12 @@
<script setup>
import moment from "moment";
import { listHolidays } from "@/api/system/holiday";
import { WEEKS } from "@/enums/appEnums";
const year = ref(moment().year() + '');
const holidays = ref([]);
const weeks = ["一", "二", "三", "四", "五", "六", "日"];
function getHolidays() {
listHolidays(year.value).then((data) => {

4
src/views/system/Menu.vue

@ -179,7 +179,7 @@
</div>
</div>
</el-form-item>
<el-form-item
<!-- <el-form-item
v-if="formData.menuType == MenuEnum.MENU"
label="路由参数"
prop="params"
@ -197,7 +197,7 @@
"admin"}``id=1&name=admin`
</div>
</div>
</el-form-item>
</el-form-item> -->
<el-form-item
v-if="formData.menuType === MenuEnum.MENU"
label="打开新页面"

95
src/views/system/Police.vue

@ -109,36 +109,11 @@
getWorkYear(row.employmentDate)
}}</span>
</div>
</div>
<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.haveChildren }}</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>
@ -166,19 +141,20 @@
</div>
</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="180" />
<el-table-column label="人员属性" width="160" align="center">
<el-table-column label="人员属性" width="120" align="center">
<template #default="{ row }">
<span>{{
getDictLable(dict.personType, row.personType)
}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<el-table-column label="职位" prop="position" width="120" />
<el-table-column label="备注" prop="job" width="140" />
<el-table-column label="身份证" prop="idCode" width="200" />
<el-table-column label="电话" prop="mobile" width="180" />
<el-table-column label="操作" width="220">
<template #default="{ row }">
<el-button
type="primary"
@ -195,6 +171,13 @@
v-if="row.idCode"
>权限设置</el-button
>
<el-button
type="danger"
link
@click="handleDel(row)"
v-perms="['police:del']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
@ -226,6 +209,7 @@
v-model="authForm.departs"
multiple
check-strictly
:show-root="true"
/>
</el-form-item>
<el-form-item label="业务权限(问题来源)">
@ -237,6 +221,7 @@
filterable
v-model="authForm.sources"
multiple
/>
</el-form-item>
</el-form>
@ -310,9 +295,21 @@
message: '请选择所属单位',
}"
>
<depart-tree-select v-model="form.orgId" />
<div style="width: 280px">
<depart-tree-select v-model="form.orgId" />
</div>
</el-form-item>
<el-form-item label="职位" prop="position">
<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="职位" prop="position" v-if="form.personType === PersonType.POLICE">
<el-select
v-model="form.position"
clearable
@ -325,7 +322,7 @@
<el-form-item label="角色" prop="policeRole">
<el-select
clearable
v-model="query.policeRole"
v-model="form.policeRole"
style="width: 280px"
>
<el-option
@ -353,23 +350,15 @@
:disabled-date="
(time) => time.getTime() > new Date().getTime()
"
style="width: 280px"
/>
<span class="ml-10" v-if="form.employmentDate"
>工龄{{ getWorkYear(form.employmentDate) }}</span
>
</div>
</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-form-item label="婚姻状况">
<el-radio-group v-model="form.maritalStatus">
<el-radio
v-for="item in dict.maritalStatus"
@ -384,7 +373,7 @@
<el-radio value="无子女"></el-radio>
<el-radio value="有子女"></el-radio>
</el-radio-group>
</el-form-item>
</el-form-item> -->
<!-- <el-form-item label="学历">
<el-select v-model="form.education">
<el-option
@ -403,17 +392,20 @@
</el-dialog>
</template>
<script setup>
import { UserFilled } from "@element-plus/icons-vue";
import {
listPolice,
getPoliceAuths,
addPolice,
updatePolice,
delPolice,
updatePoliceAuths,
} from "@/api/system/police";
import { PersonType } from '@/enums/dictEnums'
import useCatchStore from "@/stores/modules/catch";
import feedback from "@/utils/feedback";
import { getDictLable } from "@/utils/util";
import { UserFilled } from "@element-plus/icons-vue";
import moment from "moment";
const catchStore = useCatchStore();
@ -527,6 +519,13 @@ function getWorkYear(employmentDate) {
}
return moment().diff(moment(employmentDate), "month") + "个月";
}
async function handleDel(row) {
await feedback.confirm(`确定要删除 ${row.name}`)
await delPolice(row.id)
feedback.msgSuccess('操作成功')
getList()
}
</script>
<style lang="scss" scoped>
</style>

139
src/views/system/Role.vue

@ -5,7 +5,10 @@
<el-row>
<el-col :span="6">
<el-form-item label="角色名">
<el-input placeholder="请输入角色名" v-model="query.roleName" />
<el-input
placeholder="请输入角色名"
v-model="query.roleName"
/>
</el-form-item>
</el-col>
</el-row>
@ -15,13 +18,15 @@
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增角色</el-button>
新增角色</el-button
>
<div>
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</div>
@ -43,13 +48,19 @@
/>
<el-table-column label="操作" width="220">
<template #default="{ row }">
<el-button type="primary" link @click="handleOpenRoleMenu(row.roleCode)"
<el-button
type="primary"
link
@click="handleOpenRoleMenu(row.roleCode)"
>菜单权限</el-button
>
<el-button type="primary" link @click="handleEdit(row)"
>编辑</el-button
>
<el-button type="danger" link @click="handleDel(row.roleId)"
<el-button
type="danger"
link
@click="handleDel(row.roleId)"
>删除</el-button
>
</template>
@ -58,23 +69,37 @@
</div>
</div>
<el-dialog :title="mode === 'add' ? '新增角色' : '编辑角色'" v-model="show" width="500">
<el-dialog
:title="mode === 'add' ? '新增角色' : '编辑角色'"
v-model="show"
width="500"
>
<el-form :label-width="120" ref="formRef" :model="form">
<el-form-item label="角色名">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
<el-input
v-model="form.roleName"
placeholder="请输入角色名称"
/>
</el-form-item>
<el-form-item label="角色编码">
<el-input v-model="form.roleCode" placeholder="请输入角色编码" />
<el-input
v-model="form.roleCode"
placeholder="请输入角色编码"
/>
</el-form-item>
<el-form-item label="级别">
<el-select v-model="form.level" placeholder="请选择角色级别">
<el-option :value="1" label="市局" />
<el-option :value="2" label="二级机构" />
<el-option :value="3" label="三级机构" />
<el-option :value="1" label="市局" />
<el-option :value="2" label="二级机构" />
<el-option :value="3" label="三级机构" />
</el-select>
</el-form-item>
<el-form-item label="角色描述">
<el-input type="textarea" v-model="form.roleDesc" placeholder="请输入角色描述" />
<el-input
type="textarea"
v-model="form.roleDesc"
placeholder="请输入角色描述"
/>
</el-form-item>
</el-form>
<footer class="flex end">
@ -85,7 +110,7 @@
<el-dialog title="菜单权限" v-model="authShow" width="500">
<header class="flex v-center">
<label class="mr-20" style="font-weight: 700;">配置</label>
<label class="mr-20" style="font-weight: 700">配置</label>
<el-checkbox v-model="checkStrictly" label="父子联动" />
</header>
<div style="padding: 20px" v-loading="authLoading">
@ -100,17 +125,29 @@
</div>
<footer class="flex end">
<el-button @click="authShow = false">取消</el-button>
<el-button type="primary" @click="handleUpdateRoleMenu" :loading="authLoading">确定</el-button>
<el-button
type="primary"
@click="handleUpdateRoleMenu"
:loading="authLoading"
>确定</el-button
>
</footer>
</el-dialog>
</template>
<script lang="ts" setup>
import { listRole, addRole, updateRole, delRole, getRoleMenu, updateRoleMenu } from "@/api/system/role";
import {
listRole,
addRole,
updateRole,
delRole,
getRoleMenu,
updateRoleMenu,
} from "@/api/system/role";
import { listMenu } from "@/api/system/menu";
import feedback from '@/utils/feedback'
import feedback from "@/utils/feedback";
const roles = ref<any[]>([]);
const query = ref({})
const query = ref({});
function getList() {
listRole(query.value).then((data) => {
roles.value = data;
@ -119,11 +156,11 @@ function getList() {
getList();
function reset() {
query.value = {}
query.value = {};
getList();
}
const show = ref(false)
const show = ref(false);
const menus = ref([]);
function getMenus() {
@ -133,19 +170,19 @@ function getMenus() {
}
getMenus();
const form = ref({})
const formRef = ref(null)
const form = ref({});
const formRef = ref(null);
const mode = ref('add')
const mode = ref("add");
function handleAdd() {
show.value = true
mode.value = 'add'
show.value = true;
mode.value = "add";
}
function handleEdit(row) {
show.value = true
mode.value = 'edit'
form.value = row
show.value = true;
mode.value = "edit";
form.value = row;
}
const handleDel = async (id: string) => {
@ -155,41 +192,39 @@ const handleDel = async (id: string) => {
getList();
};
function submit() {
formRef.value.validate((flag) => {
if (flag) {
if (mode.value === 'add') {
addRole(form.value).then(() => {
form.value = {}
show.value = false
getList()
})
}
}
})
async function submit() {
await formRef.value.validate();
if (mode.value === "add") {
await addRole(form.value);
} else {
await updateRole(form.value);
}
form.value = {};
show.value = false;
getList();
}
const authShow = ref<bool>(false);
const authLoading = ref(true)
const authLoading = ref(true);
const checkStrictly = ref(false)
const roleMenuTreeRef = ref(null)
let activeRoleCode = '';
const checkStrictly = ref(false);
const roleMenuTreeRef = ref(null);
let activeRoleCode = "";
async function handleOpenRoleMenu(roleCode) {
authLoading.value = true
activeRoleCode = roleCode
authShow.value = true
const data = await getRoleMenu(roleCode)
roleMenuTreeRef.value.setCheckedKeys(data)
authLoading.value = false
authLoading.value = true;
activeRoleCode = roleCode;
authShow.value = true;
const data = await getRoleMenu(roleCode);
roleMenuTreeRef.value.setCheckedKeys(data);
authLoading.value = false;
}
async function handleUpdateRoleMenu() {
const menuIds = roleMenuTreeRef.value.getCheckedKeys();
authLoading.value = true
await updateRoleMenu(activeRoleCode, menuIds)
authShow.value = false
authLoading.value = true;
await updateRoleMenu(activeRoleCode, menuIds);
authShow.value = false;
feedback.msgSuccess("操作成功");
}
</script>

92
src/views/system/User.vue

@ -1,6 +1,6 @@
<template>
<div class="container">
<header>
<header class="mb-20">
<el-form :label-width="114">
<el-row>
<el-col :span="6">
@ -19,47 +19,85 @@
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="角色">
<el-select
v-model="query.roleId"
placeholder="请选择角色"
multiple
clearable
>
<el-option
v-for="item in roles"
:key="item.roleId"
:value="item.roleId"
:label="item.roleName"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<div class="flex end">
<el-button type="primary" @click="getList">
<template #icon>
<icon name="el-icon-Search" />
</template>
查询</el-button
>
<el-button @click="reset">重置</el-button>
</div>
</el-col>
</el-row>
</el-form>
<div class="mb-25 flex end">
<!-- <el-button type="primary">新增用户</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="users">
<el-table-column label="登录名" prop="userName" />
<el-table-column label="姓名" prop="nickName" />
<el-table-column label="手机号" prop="mobile" />
<el-table-column label="状态" width="100">
<template #default="{ row }">
<el-tag type="success" v-if="row.status === 1"
>正常</el-tag
>
</template>
</el-table-column>
<el-table-column label="角色" width="300">
<el-table-column label="登录名" prop="userName" width="180" />
<el-table-column label="姓名" prop="nickName" width="120" />
<el-table-column label="角色">
<template #default="{ row }">
<el-tag
v-for="item in row.roleNames"
:key="item"
size="small"
class="mr-4"
>{{ item }}</el-tag
>
</template>
</el-table-column>
<el-table-column label="最后更新时间" prop="updateTime" />
<el-table-column label="操作">
<el-table-column
label="管理员类型"
prop="userType"
align="center"
width="200"
>
<template #default="{ row }">
<span>{{
row.userType === "super"
? "超级管理员"
: "普通管理员"
}}</span>
</template>
</el-table-column>
<el-table-column
label="最后更新时间"
prop="updateTime"
width="200"
/>
<el-table-column label="状态" width="100">
<template #default="{ row }">
<el-tag type="success" v-if="row.status === 1"
>正常</el-tag
>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)" v-perms="['user:edit']"
<el-button
type="primary"
link
@click="handleEdit(row)"
v-perms="['user:edit']"
>编辑</el-button
>
</template>

10
vite.config.ts

@ -70,16 +70,16 @@ export default ({ mode }) => {
},
postcss: {
plugins: [
// postCssPxToRem({
// rootValue: 192,
// propList: ['*'],
// })
postCssPxToRem({
rootValue: 192,
propList: ['*'],
})
]
}
},
build: {
outDir: 'v2',
target: "es2015"
// target: "es2015"
}
})
}

Loading…
Cancel
Save