This commit is contained in:
zhoutianchi
2026-01-29 14:02:46 +08:00
40 changed files with 6908 additions and 4623 deletions

View File

@@ -0,0 +1,103 @@
# hooks/table 使用方法检查
## 一、useTable 源码要点(`src/hooks/table.ts`
### 1. 入参 `BasicTableProps`
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `createdIsNeed` | `boolean` | **true** | 是否在 `onMounted` 时自动请求列表 |
| `isPage` | `boolean` | true | 是否分页 |
| `queryForm` | `any` | `{}` | 查询条件,会合并到请求参数 |
| `pageList` | `(...arg: any) => Promise<any>` | - | **必填**,分页接口方法 |
| `props` | `object` | `{ item: 'records', totalCount: 'total' }` | 列表/总数的数据路径 |
| `validate` | `Function` | - | 请求前校验,不通过则不请求 |
| `onLoaded` | `Function` | - | 请求成功、写入 `dataList` 后的回调 |
| `onCascaded` | `Function` | - | 级联回调 |
| `pagination` | `Pagination` | 见源码 | 分页配置 |
### 2. 内部逻辑
- **请求参数**`query()` 调用 `state.pageList({ ...state.queryForm, current, size, descs, ascs })`
- **响应处理**:用 `state.props.item``state.props.totalCount``res.data` 取列表和总数,写入 `state.dataList``state.pagination.total`
- **首次加载**:在 **hooks 内部的 `onMounted`** 里,若 `state.createdIsNeed === true` 则执行一次 `query()`
- **注意**`useTable` **不 return state**,调用方需要自己持有一份 `state`(通常用 `reactive`)并传给 `useTable(state)`表格数据、分页、loading 都写在这份 `state` 上。
### 3. 返回值
```ts
{
getDataList, // (refresh?: any) => void默认重置到第 1 页再请求getDataList(false) 不重置页码
currentChangeHandle, // 页码变化时调用
sizeChangeHandle, // 每页条数变化时调用
sortChangeHandle, // 排序变化时调用(若表格支持 sortable="custom"
tableStyle, // { cellStyle, headerCellStyle }
downBlobFile // 下载文件
}
```
---
## 二、推荐用法(与 search-form 配合)
### 1. 定义 state 并传入 useTable
```ts
import { BasicTableProps, useTable } from '/@/hooks/table'
const search = reactive({ deptCode: '', realName: '', teacherNo: '' })
const state = reactive<BasicTableProps>({
queryForm: search, // 与 search-form 的 :model 同一对象
pageList: fetchList, // 或自定义方法合并额外参数
// createdIsNeed 不写则默认为 true首屏自动请求
})
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
```
- **state 由调用方定义并传入**,不要在解构时期望 `useTable` 返回 `state`(源码未返回)。
### 2. 模板绑定
- 表格:`:data="state.dataList"``v-loading="state.loading"``tableStyle` 用于 `cell-style` / `header-cell-style`
- 分页:`v-bind="state.pagination"` 或分别绑定 `current`/`size`/`total`,事件用 `@current-change="currentChangeHandle"``@size-change="sizeChangeHandle"`
### 3. 查询 / 重置 / 刷新
- 点击「查询」:先更新 `search`(或额外参数),再 `getDataList()`(会回到第 1 页)。
- 重置:清空 `search`(及 ref 里的额外参数),可选 `searchFormRef?.resetFields()`,再 `getDataList()`
- 只刷新当前页:`getDataList(false)`
### 4. 与 createdIsNeed 的关系
- **createdIsNeed: true默认**hooks 内部 onMounted 会自动调一次 `query()`**页面里不需要再在 onMounted 里调 getDataList()**,否则会重复请求。
- **createdIsNeed: false**:不在挂载时请求,需要自己在合适时机(例如 onMounted 或某个条件满足后)调用 `getDataList()`
---
## 三、professionaltitlerelation/index.vue 检查结果
| 检查项 | 状态 | 说明 |
|--------|------|------|
| queryForm 使用 search | ✅ | 与 search-form 的 model 一致 |
| pageList 返回结构 | ✅ | 返回 `{ data: { records, total } }`,与默认 props 一致 |
| createdIsNeed | ✅ | 未配置即默认 true首屏由 useTable 自动请求 |
| onMounted 不重复请求 | ✅ | 仅 `loadDictData()`,未再调 getDataList |
| 表格绑定 state.dataList / state.loading | ✅ | 正确 |
| 分页绑定 state.pagination + currentChangeHandle/sizeChangeHandle | ✅ | 正确 |
| 查询 handleFilter → getDataList() | ✅ | 正确 |
| 重置 resetQuery → 清空 search + getDataList() | ✅ | 正确 |
| 删除/审核后 getDataList() | ✅ | 正确 |
| tableStyle 用于 el-table | ✅ | 正确 |
**结论**:当前 `professionaltitlerelation/index.vue` 对 hooks/table 的使用符合上述规范,无需修改。
---
## 四、常见注意点
1. **不要从 useTable 解构 state**:源码未返回 state应自己在页面里 `const state = reactive<BasicTableProps>({...})` 并传给 `useTable(state)`
2. **文档中若写 `const { state } = useTable(state)`**:属于文档笔误,实际应使用调用方定义的 `state`
3. **自定义 pageList 时**:返回结构需与 `props` 一致,默认即 `res.data.records``res.data.total`;若后端字段不同,可同时配置 `props: { item: 'xxx', totalCount: 'yyy' }`
4. **需要额外请求参数时**:在 `pageList` 里对入参做合并,例如 `return await fetchList({ ...queryParams, ...params.value })`

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018-2025, cyweb All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
*/
import request from '/@/utils/request';
/**
* 分页查询
* @param params 查询参数
*/
export function getPage(params?: any) {
return request({
url: '/purchase/purchasingagent/page',
method: 'get',
params
});
}
/**
* 通过id查询
* @param id ID
*/
export function getObj(id: string | number) {
return request({
url: '/purchase/purchasingagent/' + id,
method: 'get'
});
}
/**
* 新增招标代理
* @param obj 对象数据
*/
export function addObj(obj: any) {
return request({
url: '/purchase/purchasingagent',
method: 'post',
data: obj
});
}
/**
* 修改招标代理
* @param obj 对象数据
*/
export function editObj(obj: any) {
return request({
url: '/purchase/purchasingagent/edit',
method: 'post',
data: obj
});
}
/**
* 删除招标代理
* @param id ID
*/
export function delObj(id: string | number) {
return request({
url: '/purchase/purchasingagent/delete',
method: 'post',
data: id
});
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2018-2025, cyweb All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
*/
import request from '/@/utils/request';
/**
* 获取树形列表
* @param params 查询参数
*/
export function getTree(params?: any) {
return request({
url: '/purchase/purchasingcategory/tree',
method: 'get',
params
});
}
/**
* 新增
* @param obj 对象数据
*/
export function addObj(obj: any) {
return request({
url: '/purchase/purchasingcategory',
method: 'post',
data: obj
});
}
/**
* 删除
* @param id ID
*/
export function delObj(id: string | number) {
return request({
url: '/purchase/purchasingcategory/delete',
method: 'post',
data: id
});
}
/**
* 更新
* @param obj 对象数据
*/
export function editObj(obj: any) {
return request({
url: '/purchase/purchasingcategory/edit',
method: 'post',
data: obj
});
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 2018-2025, cyweb All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
*/
import request from '/@/utils/request';
/**
* 分页查询
* @param params 查询参数
*/
export function getPage(params?: any) {
return request({
url: '/purchase/purchasingapply/page',
method: 'get',
params
});
}
/**
* 通过id查询
* @param id ID
*/
export function getObj(id: number) {
return request({
url: '/purchase/purchasingapply/' + id,
method: 'get'
});
}
/**
* 新增采购申请(提交并启动流程)
* @param obj 对象数据
*/
export function addObj(obj: any) {
return request({
url: '/purchase/purchasingapply/submit',
method: 'post',
data: obj
});
}
/**
* 暂存采购申请
* @param obj 对象数据
*/
export function tempStore(obj: any) {
return request({
url: '/purchase/purchasingapply/temp-store',
method: 'post',
data: obj
});
}
/**
* 提交采购申请(启动流程)
* @param obj 对象数据
*/
export function submitObj(obj: any) {
return request({
url: '/purchase/purchasingapply/submit',
method: 'post',
data: obj
});
}
/**
* 修改采购申请
* @param obj 对象数据
*/
export function editObj(obj: any) {
return request({
url: '/purchase/purchasingapply/edit',
method: 'post',
data: obj
});
}
/**
* 删除采购申请
* @param id ID
*/
export function delObj(id: number) {
return request({
url: '/purchase/purchasingapply/delete',
method: 'post',
data: id
});
}

View File

@@ -0,0 +1,128 @@
<template>
<el-dialog
:title="dataForm.id ? '编辑' : '新增'"
v-model="visible"
width="600px"
:close-on-click-modal="false"
draggable>
<el-form
ref="formRef"
:model="dataForm"
:rules="dataRules"
label-width="100px"
v-loading="loading">
<el-form-item label="代理名称" prop="agentName">
<el-input
v-model="dataForm.agentName"
placeholder="请输入代理名称"
clearable />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
type="textarea"
:rows="3"
placeholder="请输入备注"
clearable />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="PurchaseAgentForm">
import { reactive, ref, nextTick } from 'vue'
import { getObj, addObj, editObj } from '/@/api/finance/purchaseagent';
import { useMessage } from '/@/hooks/message';
// 定义子组件向父组件传值/事件
const emit = defineEmits(['refresh']);
// 定义变量内容
const formRef = ref();
const dataForm = reactive({
id: '',
agentName: '',
remark: '',
});
const visible = ref(false);
const loading = ref(false);
const dataRules = ref({
agentName: [
{ required: true, message: '请输入代理名称', trigger: 'blur' }
],
});
// 打开弹窗
const openDialog = async (type: string, rowData?: any) => {
visible.value = true;
dataForm.id = '';
dataForm.agentName = '';
dataForm.remark = '';
nextTick(() => {
formRef.value?.resetFields();
if (type === 'edit' && rowData?.id) {
// 编辑时,先获取详情数据
loading.value = true;
getObj(rowData.id).then((res: any) => {
if (res.data) {
Object.assign(dataForm, {
id: res.data.id || '',
agentName: res.data.agentName || '',
remark: res.data.remark || '',
});
}
loading.value = false;
}).catch((err: any) => {
useMessage().error(err.msg || '获取详情失败');
loading.value = false;
});
}
});
};
// 提交
const onSubmit = async () => {
// 立即设置 loading防止重复点击
if (loading.value) return;
loading.value = true;
try {
const valid = await formRef.value.validate().catch(() => {});
if (!valid) {
loading.value = false;
return false;
}
if (dataForm.id) {
await editObj(dataForm);
useMessage().success('编辑成功');
} else {
await addObj(dataForm);
useMessage().success('新增成功');
}
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg || (dataForm.id ? '编辑失败' : '新增失败'));
} finally {
loading.value = false;
}
};
// 暴露变量
defineExpose({
openDialog,
});
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,185 @@
<template>
<div class="modern-page-container">
<div class="page-wrapper">
<!-- 搜索表单卡片 -->
<el-card v-show="showSearch" class="search-card" shadow="never">
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon class="title-icon"><Search /></el-icon>
筛选条件
</span>
</div>
</template>
<el-form :model="state.queryForm" ref="searchFormRef" :inline="true" @keyup.enter="getDataList" class="search-form">
<el-form-item label="代理名称" prop="agentName">
<el-input
v-model="state.queryForm.agentName"
placeholder="请输入代理名称"
clearable
style="width: 200px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
<el-button icon="Refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 内容卡片 -->
<el-card class="content-card" shadow="never">
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon class="title-icon"><Document /></el-icon>
招标代理管理
</span>
<div class="header-actions">
<el-button
icon="FolderAdd"
type="primary"
@click="formDialogRef.openDialog('add')">
新增
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
</div>
</div>
</template>
<!-- 表格 -->
<el-table
ref="tableRef"
:data="state.dataList"
v-loading="state.loading"
stripe
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
class="modern-table">
<el-table-column type="index" label="序号" width="70" align="center">
<template #header>
<el-icon><List /></el-icon>
</template>
</el-table-column>
<el-table-column prop="agentName" label="代理名称" min-width="200" show-overflow-tooltip>
<template #header>
<el-icon><Document /></el-icon>
<span style="margin-left: 4px">代理名称</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="300" show-overflow-tooltip>
<template #header>
<el-icon><EditPen /></el-icon>
<span style="margin-left: 4px">备注</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180" show-overflow-tooltip>
<template #header>
<el-icon><Clock /></el-icon>
<span style="margin-left: 4px">创建时间</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="150">
<template #default="scope">
<el-button
icon="Edit"
link
type="primary"
@click="formDialogRef.openDialog('edit', scope.row)">
编辑
</el-button>
<el-button
icon="Delete"
link
type="danger"
@click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="state.total > 0"
:total="state.total"
v-model:page="state.page"
v-model:limit="state.limit"
@pagination="getDataList"
/>
</el-card>
</div>
<!-- 编辑新增表单对话框 -->
<FormDialog ref="formDialogRef" @refresh="getDataList" />
</div>
</template>
<script setup lang="ts" name="PurchaseAgent">
import { ref, reactive, defineAsyncComponent } from 'vue'
import { BasicTableProps, useTable } from "/@/hooks/table";
import { getPage, delObj } from "/@/api/finance/purchaseagent";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { List, Document, EditPen, Clock, Search } from '@element-plus/icons-vue'
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义变量内容
const tableRef = ref()
const formDialogRef = ref()
const searchFormRef = ref()
const showSearch = ref(true)
/**
* 定义响应式表格数据
*/
const state: BasicTableProps = reactive<BasicTableProps>({
pageList: getPage,
queryForm: {
agentName: '',
},
createdIsNeed: true
});
/**
* 使用 useTable 定义表格相关操作
*/
const { getDataList, tableStyle } = useTable(state);
/**
* 重置搜索表单
*/
const handleReset = () => {
searchFormRef.value?.resetFields();
getDataList();
};
/**
* 删除当前行
* @param row - 当前行数据
*/
const handleDelete = async (row: any) => {
try {
await useMessageBox().confirm('确定要删除该记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
} catch {
return;
}
try {
await delObj(row.id);
useMessage().success('删除成功');
getDataList();
} catch (err: any) {
useMessage().error(err.msg || '删除失败');
}
};
</script>
<style scoped lang="scss">
@import '/@/assets/styles/modern-page.scss';
</style>

View File

@@ -0,0 +1,182 @@
<template>
<el-dialog
:title="dataForm.id ? '编辑' : '新增'"
v-model="visible"
width="600px"
:close-on-click-modal="false"
draggable>
<el-form
ref="formRef"
:model="dataForm"
:rules="dataRules"
label-width="100px"
v-loading="loading">
<el-form-item label="父级节点" prop="parentCode">
<el-tree-select
v-model="dataForm.parentCode"
:data="parentData"
:props="{ value: 'code', label: 'name', children: 'children' }"
class="w100"
clearable
check-strictly
:render-after-expand="false"
placeholder="请选择父级节点(不选则为根节点)"
/>
</el-form-item>
<el-form-item label="品目编码" prop="code">
<el-input
v-model="dataForm.code"
placeholder="请输入品目编码"
clearable
:disabled="!!dataForm.id" />
</el-form-item>
<el-form-item label="品目名称" prop="name">
<el-input
v-model="dataForm.name"
placeholder="请输入品目名称"
clearable />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
type="textarea"
:rows="3"
placeholder="请输入备注"
clearable />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="PurchasingCategoryForm">
import { reactive, ref, nextTick } from 'vue'
import { getTree, addObj, editObj } from '/@/api/finance/purchasingcategory';
import { useMessage } from '/@/hooks/message';
// 定义子组件向父组件传值/事件
const emit = defineEmits(['refresh']);
// 定义变量内容
const formRef = ref();
const dataForm = reactive({
id: '',
parentCode: '',
code: '',
name: '',
remark: '',
isMallService: '',
isMallProject: '',
});
const parentData = ref<any[]>([]);
const visible = ref(false);
const loading = ref(false);
const dataRules = ref({
code: [
{ required: true, message: '请输入品目编码', trigger: 'blur' }
],
name: [
{ required: true, message: '请输入品目名称', trigger: 'blur' }
],
});
// 打开弹窗
const openDialog = (type: string, rowData?: any) => {
visible.value = true;
dataForm.id = '';
dataForm.parentCode = '';
dataForm.code = '';
dataForm.name = '';
dataForm.remark = '';
dataForm.isMallService = '';
dataForm.isMallProject = '';
nextTick(() => {
formRef.value?.resetFields();
if (type === 'add' && rowData?.code) {
// 新增时rowData 是父节点数据,设置父级编码
dataForm.parentCode = rowData.code;
} else if (type === 'edit' && rowData) {
// 编辑时rowData 是当前行数据
Object.assign(dataForm, {
id: rowData.id || '',
parentCode: rowData.parentCode || '',
code: rowData.code || '',
name: rowData.name || '',
remark: rowData.remark || '',
isMallService: rowData.isMallService || '',
isMallProject: rowData.isMallProject || '',
});
}
});
getTreeData();
};
// 提交
const onSubmit = async () => {
// 立即设置 loading防止重复点击
if (loading.value) return;
loading.value = true;
try {
const valid = await formRef.value.validate().catch(() => {});
if (!valid) {
loading.value = false;
return false;
}
if (dataForm.id) {
await editObj(dataForm);
useMessage().success('编辑成功');
} else {
await addObj(dataForm);
useMessage().success('新增成功');
}
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg || (dataForm.id ? '编辑失败' : '新增失败'));
} finally {
loading.value = false;
}
};
// 从后端获取树形数据
const getTreeData = async () => {
try {
const res = await getTree();
parentData.value = [];
const root = {
code: '',
name: '根节点',
children: [] as any[],
};
if (res.data && Array.isArray(res.data)) {
root.children = res.data;
}
parentData.value.push(root);
} catch (err: any) {
useMessage().error(err.msg || '获取树形数据失败');
parentData.value = [];
}
};
// 暴露变量
defineExpose({
openDialog,
});
</script>
<style scoped>
.w100 {
width: 100%;
}
</style>

View File

@@ -0,0 +1,164 @@
<template>
<div class="modern-page-container">
<div class="page-wrapper">
<!-- 内容卡片 -->
<el-card class="content-card" shadow="never">
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon class="title-icon"><Document /></el-icon>
采购品目管理
</span>
<div class="header-actions">
<el-button
icon="FolderAdd"
type="primary"
@click="formDialogRef.openDialog('add')">
新增
</el-button>
<right-toolbar class="ml10" />
</div>
</div>
</template>
<!-- 树形表格 -->
<el-table
ref="tableRef"
:data="state.dataList"
v-loading="state.loading"
stripe
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
class="modern-table"
row-key="code"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
<el-table-column type="index" label="序号" width="70" align="center">
<template #header>
<el-icon><List /></el-icon>
</template>
<template #default="{ $index, row }">
{{ getRowIndex($index, row) }}
</template>
</el-table-column>
<el-table-column prop="code" label="品目编码" min-width="150" show-overflow-tooltip>
<template #header>
<el-icon><DocumentCopy /></el-icon>
<span style="margin-left: 4px">品目编码</span>
</template>
</el-table-column>
<el-table-column prop="name" label="品目名称" min-width="200" show-overflow-tooltip>
<template #header>
<el-icon><Document /></el-icon>
<span style="margin-left: 4px">品目名称</span>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip>
<template #header>
<el-icon><EditPen /></el-icon>
<span style="margin-left: 4px">备注</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="150">
<template #default="scope">
<el-button
icon="Edit"
link
type="primary"
@click="formDialogRef.openDialog('edit', scope.row)">
编辑
</el-button>
<el-button
icon="Delete"
link
type="danger"
@click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<!-- 编辑新增表单对话框 -->
<FormDialog ref="formDialogRef" @refresh="getDataList" />
</div>
</template>
<script setup lang="ts" name="PurchasingCategory">
import { ref, reactive, defineAsyncComponent } from 'vue'
import { BasicTableProps, useTable } from "/@/hooks/table";
import { getTree, delObj } from "/@/api/finance/purchasingcategory";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { List, Document, DocumentCopy, EditPen } from '@element-plus/icons-vue'
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义变量内容
const tableRef = ref()
const formDialogRef = ref()
/**
* 查询树形数据方法
* @param params - 查询参数
* @returns Promise<any>
*/
const queryTree = (params?: any) => {
return getTree(params);
};
/**
* 定义响应式表格数据
*/
const state: BasicTableProps = reactive<BasicTableProps>({
pageList: queryTree,
queryForm: {},
isPage: false, // 树形表格不分页
});
/**
* 使用 useTable 定义表格相关操作
*/
const { getDataList, tableStyle } = useTable(state);
/**
* 计算行序号(考虑树形结构)
*/
const getRowIndex = (index: number, row: any) => {
// 对于树形表格,序号需要根据实际显示的行来计算
// 这里简化处理,直接返回 index + 1
return index + 1;
};
/**
* 删除当前行
* @param row - 当前行数据
*/
const handleDelete = async (row: any) => {
try {
await useMessageBox().confirm('确定要删除该记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
} catch {
return;
}
try {
// 使用 id 或 code 作为删除参数(根据后端接口决定)
const deleteId = row.id || row.code;
await delObj(deleteId);
useMessage().success('删除成功');
getDataList();
} catch (err: any) {
useMessage().error(err.msg || '删除失败');
}
};
</script>
<style scoped lang="scss">
@import '/@/assets/styles/modern-page.scss';
</style>

View File

@@ -0,0 +1,434 @@
<template>
<el-dialog
:title="dialogTitle"
v-model="visible"
width="900px"
:close-on-click-modal="false"
draggable>
<el-form
ref="formRef"
:model="dataForm"
:rules="dataRules"
label-width="140px"
v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="采购项目名称" prop="projectName">
<el-input
v-model="dataForm.projectName"
placeholder="请输入采购项目名称"
clearable
:disabled="isView" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="项目类别" prop="projectType">
<el-select
v-model="dataForm.projectType"
placeholder="请选择项目类别"
clearable
:disabled="isView"
style="width: 100%">
<el-option label="货物" value="A" />
<el-option label="工程" value="B" />
<el-option label="服务" value="C" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="品目编码" prop="categoryCode">
<el-tree-select
v-model="dataForm.categoryCode"
:data="categoryTreeData"
:props="{ value: 'code', label: 'name', children: 'children' }"
placeholder="请选择品目编码"
clearable
check-strictly
:render-after-expand="false"
:disabled="isView"
style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="填报日期" prop="applyDate">
<el-date-picker
v-model="dataForm.applyDate"
type="date"
placeholder="请选择填报日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:disabled="isView"
style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="采购内容" prop="projectContent" class="mb20">
<el-input
v-model="dataForm.projectContent"
type="textarea"
:rows="3"
placeholder="请输入采购内容"
clearable
:disabled="isView" />
</el-form-item>
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="资金来源" prop="fundSource">
<el-input
v-model="dataForm.fundSource"
placeholder="请输入资金来源"
clearable
:disabled="isView" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="预算金额(元)" prop="budget">
<el-input-number
v-model="dataForm.budget"
:min="0.01"
:precision="2"
placeholder="请输入预算金额"
:disabled="isView"
style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="是否集采" prop="isCentralized">
<el-select
v-model="dataForm.isCentralized"
placeholder="请选择是否集采"
clearable
:disabled="isView"
style="width: 100%">
<el-option label="否" value="0" />
<el-option label="是" value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="是否特殊情况" prop="isSpecial">
<el-select
v-model="dataForm.isSpecial"
placeholder="请选择是否特殊情况"
clearable
:disabled="isView"
style="width: 100%">
<el-option label="否" value="0" />
<el-option label="紧急" value="1" />
<el-option label="单一" value="2" />
<el-option label="进口" value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="采购形式" prop="purchaseMode">
<el-select
v-model="dataForm.purchaseMode"
placeholder="请选择采购形式"
clearable
:disabled="isView"
style="width: 100%">
<el-option label="部门自行采购" value="0" />
<el-option label="学校统一采购" value="2" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="学校统一采购方式" prop="purchaseSchool">
<el-select
v-model="dataForm.purchaseSchool"
placeholder="请选择学校统一采购方式"
clearable
:disabled="isView || dataForm.purchaseMode !== '2'"
style="width: 100%">
<el-option label="无" value="0" />
<el-option label="政府采购" value="1" />
<el-option label="学校自主采购" value="2" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="采购方式" prop="purchaseType" class="mb20">
<el-input
v-model="dataForm.purchaseType"
placeholder="请输入采购方式"
clearable
:disabled="isView" />
</el-form-item>
<el-form-item label="附件" prop="fileIds" class="mb20">
<upload-file
v-model="dataForm.fileIds"
:limit="10"
:disabled="isView"
upload-file-url="/purchase/purchasingfiles/upload" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
type="textarea"
:rows="3"
placeholder="请输入备注"
clearable
:disabled="isView" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">{{ isView ? '关闭' : '取消' }}</el-button>
<template v-if="!isView">
<el-button v-if="dataForm.id && dataForm.status === '-1'" type="warning" @click="handleTempStore" :disabled="loading">暂存</el-button>
<el-button type="primary" @click="handleSubmit" :disabled="loading">{{ dataForm.id ? '保存' : '提交' }}</el-button>
</template>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="PurchasingRequisitionForm">
import { reactive, ref, nextTick, computed } from 'vue'
import { getObj, addObj, editObj, tempStore, submitObj } from '/@/api/finance/purchasingrequisition';
import { getTree } from '/@/api/finance/purchasingcategory';
import { useMessage } from '/@/hooks/message';
import UploadFile from '/@/components/Upload/index.vue';
// 定义子组件向父组件传值/事件
const emit = defineEmits(['refresh']);
// 定义变量内容
const formRef = ref();
const dataForm = reactive({
id: '',
projectName: '',
projectType: '',
projectContent: '',
applyDate: '',
fundSource: '',
budget: null as number | null,
isCentralized: '',
isSpecial: '',
purchaseMode: '',
purchaseSchool: '',
purchaseType: '',
categoryCode: '',
fileIds: '',
remark: '',
status: '',
});
const categoryTreeData = ref<any[]>([]);
const visible = ref(false);
const loading = ref(false);
const dialogType = ref<'add' | 'edit' | 'view'>('add');
const isView = computed(() => dialogType.value === 'view');
const dialogTitle = computed(() => {
if (dialogType.value === 'view') return '查看采购申请';
if (dialogType.value === 'edit') return '编辑采购申请';
return '新增采购申请';
});
const dataRules = reactive({
projectContent: [
{ required: true, message: '采购内容不能为空', trigger: 'blur' }
],
budget: [
{ required: true, message: '预算金额不能为空', trigger: 'blur' },
{ type: 'number', min: 0.01, message: '预算金额必须大于0.01', trigger: 'blur' }
],
isCentralized: [
{ required: true, message: '请选择是否集采', trigger: 'change' }
],
isSpecial: [
{ required: true, message: '请选择是否特殊情况', trigger: 'change' }
],
});
// 打开弹窗
const openDialog = async (type: 'add' | 'edit' | 'view', rowData?: any) => {
dialogType.value = type;
visible.value = true;
// 重置表单
dataForm.id = '';
dataForm.projectName = '';
dataForm.projectType = '';
dataForm.projectContent = '';
dataForm.applyDate = '';
dataForm.fundSource = '';
dataForm.budget = null;
dataForm.isCentralized = '';
dataForm.isSpecial = '';
dataForm.purchaseMode = '';
dataForm.purchaseSchool = '';
dataForm.purchaseType = '';
dataForm.categoryCode = '';
dataForm.fileIds = '';
dataForm.remark = '';
dataForm.status = '';
await getCategoryTreeData();
nextTick(() => {
formRef.value?.resetFields();
if (type === 'edit' || type === 'view') {
loading.value = true;
getObj(rowData.id)
.then((res) => {
Object.assign(dataForm, {
id: res.data.id || '',
projectName: res.data.projectName || '',
projectType: res.data.projectType || '',
projectContent: res.data.projectContent || '',
applyDate: res.data.applyDate || '',
fundSource: res.data.fundSource || '',
budget: res.data.budget || null,
isCentralized: res.data.isCentralized || '',
isSpecial: res.data.isSpecial || '',
purchaseMode: res.data.purchaseMode || '',
purchaseSchool: res.data.purchaseSchool || '',
purchaseType: res.data.purchaseType || '',
categoryCode: res.data.categoryCode || '',
fileIds: res.data.fileIds ? (Array.isArray(res.data.fileIds) ? res.data.fileIds.join(',') : res.data.fileIds) : '',
remark: res.data.remark || '',
status: res.data.status || '',
});
})
.catch((err: any) => {
useMessage().error(err.msg || '获取详情失败');
})
.finally(() => {
loading.value = false;
});
}
});
};
// 获取品目树形数据
const getCategoryTreeData = async () => {
try {
const res = await getTree();
categoryTreeData.value = [];
if (res.data && Array.isArray(res.data)) {
categoryTreeData.value = res.data;
}
} catch (err: any) {
console.error('获取品目树形数据失败', err);
categoryTreeData.value = [];
}
};
// 处理文件ID字符串转数组
// 从URL中提取文件IDURL格式通常为: /admin/sys-file/show?fileName=xxx&id=xxx
const getFileIdsArray = (): string[] => {
if (!dataForm.fileIds) return [];
if (Array.isArray(dataForm.fileIds)) return dataForm.fileIds;
// 如果是逗号分隔的URL字符串需要从URL中提取文件ID
const urls = dataForm.fileIds.split(',').filter(url => url.trim());
const fileIds: string[] = [];
urls.forEach(url => {
try {
// 尝试从URL参数中提取id
const urlObj = new URL(url, window.location.origin);
const id = urlObj.searchParams.get('id') || urlObj.searchParams.get('fileName');
if (id) {
fileIds.push(id);
} else {
// 如果没有id参数尝试从路径中提取
const pathParts = urlObj.pathname.split('/');
const lastPart = pathParts[pathParts.length - 1];
if (lastPart) {
fileIds.push(lastPart);
}
}
} catch {
// 如果URL解析失败直接使用原始值
fileIds.push(url);
}
});
return fileIds;
};
// 提交(新增或编辑)
const handleSubmit = async () => {
if (loading.value) return;
loading.value = true;
try {
const valid = await formRef.value?.validate().catch(() => {});
if (!valid) {
loading.value = false;
return false;
}
const submitData = {
...dataForm,
fileIds: getFileIdsArray(),
};
if (dataForm.id) {
// 编辑
await editObj(submitData);
useMessage().success('保存成功');
} else {
// 新增(暂存,不启动流程)
await addObj(submitData);
useMessage().success('提交成功');
}
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg || (dataForm.id ? '保存失败' : '提交失败'));
} finally {
loading.value = false;
}
};
// 暂存
const handleTempStore = async () => {
if (loading.value) return;
loading.value = true;
try {
const valid = await formRef.value?.validate().catch(() => {});
if (!valid) {
loading.value = false;
return false;
}
const submitData = {
...dataForm,
fileIds: getFileIdsArray(),
};
await tempStore(submitData);
useMessage().success('暂存成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg || '暂存失败');
} finally {
loading.value = false;
}
};
// 暴露变量
defineExpose({
openDialog,
});
</script>
<style scoped>
.mb20 {
margin-bottom: 20px;
}
</style>

View File

@@ -0,0 +1,293 @@
<template>
<div class="modern-page-container">
<div class="page-wrapper">
<!-- 搜索表单卡片 -->
<el-card v-show="showSearch" class="search-card" shadow="never">
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon class="title-icon"><Search /></el-icon>
筛选条件
</span>
</div>
</template>
<el-form :model="state.queryForm" ref="searchFormRef" :inline="true" @keyup.enter="getDataList" class="search-form">
<el-form-item label="采购编号" prop="purchaseNo">
<el-input
v-model="state.queryForm.purchaseNo"
placeholder="请输入采购编号"
clearable
style="width: 200px" />
</el-form-item>
<el-form-item label="采购项目名称" prop="projectName">
<el-input
v-model="state.queryForm.projectName"
placeholder="请输入采购项目名称"
clearable
style="width: 200px" />
</el-form-item>
<el-form-item label="项目类别" prop="projectType">
<el-select
v-model="state.queryForm.projectType"
placeholder="请选择项目类别"
clearable
style="width: 200px">
<el-option label="货物" value="A" />
<el-option label="工程" value="B" />
<el-option label="服务" value="C" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="state.queryForm.status"
placeholder="请选择状态"
clearable
style="width: 200px">
<el-option label="撤回" value="-2" />
<el-option label="暂存" value="-1" />
<el-option label="运行中" value="0" />
<el-option label="完成" value="1" />
<el-option label="作废" value="2" />
<el-option label="终止" value="3" />
</el-select>
</el-form-item>
<el-form-item label="是否集采" prop="isCentralized">
<el-select
v-model="state.queryForm.isCentralized"
placeholder="请选择是否集采"
clearable
style="width: 200px">
<el-option label="否" value="0" />
<el-option label="是" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
<el-button icon="Refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 内容卡片 -->
<el-card class="content-card" shadow="never">
<template #header>
<div class="card-header">
<span class="card-title">
<el-icon class="title-icon"><Document /></el-icon>
采购申请管理
</span>
<div class="header-actions">
<el-button
icon="FolderAdd"
type="primary"
@click="formDialogRef.openDialog('add')">
新增
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
</div>
</div>
</template>
<!-- 表格 -->
<el-table
ref="tableRef"
:data="state.dataList"
v-loading="state.loading"
stripe
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
class="modern-table">
<el-table-column type="index" label="序号" width="70" align="center">
<template #header>
<el-icon><List /></el-icon>
</template>
</el-table-column>
<el-table-column prop="code" label="编号" min-width="120" show-overflow-tooltip>
<template #header>
<el-icon><DocumentCopy /></el-icon>
<span style="margin-left: 4px">编号</span>
</template>
</el-table-column>
<el-table-column prop="purchaseNo" label="采购编号" min-width="120" show-overflow-tooltip>
<template #header>
<el-icon><DocumentCopy /></el-icon>
<span style="margin-left: 4px">采购编号</span>
</template>
</el-table-column>
<el-table-column prop="projectName" label="采购项目名称" min-width="200" show-overflow-tooltip>
<template #header>
<el-icon><Document /></el-icon>
<span style="margin-left: 4px">采购项目名称</span>
</template>
</el-table-column>
<el-table-column prop="projectType" label="项目类别" width="100" align="center">
<template #header>
<el-icon><Collection /></el-icon>
<span style="margin-left: 4px">项目类别</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.projectType === 'A'" type="success">货物</el-tag>
<el-tag v-else-if="scope.row.projectType === 'B'" type="warning">工程</el-tag>
<el-tag v-else-if="scope.row.projectType === 'C'" type="info">服务</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="budget" label="预算金额(元)" width="120" align="right">
<template #header>
<el-icon><Money /></el-icon>
<span style="margin-left: 4px">预算金额</span>
</template>
<template #default="scope">
{{ scope.row.budget ? Number(scope.row.budget).toLocaleString() : '-' }}
</template>
</el-table-column>
<el-table-column prop="isCentralized" label="是否集采" width="100" align="center">
<template #header>
<el-icon><CircleCheck /></el-icon>
<span style="margin-left: 4px">是否集采</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.isCentralized === '1'" type="success"></el-tag>
<el-tag v-else-if="scope.row.isCentralized === '0'" type="info"></el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100" align="center">
<template #header>
<el-icon><InfoFilled /></el-icon>
<span style="margin-left: 4px">状态</span>
</template>
<template #default="scope">
<el-tag v-if="scope.row.status === '-2'" type="info">撤回</el-tag>
<el-tag v-else-if="scope.row.status === '-1'" type="warning">暂存</el-tag>
<el-tag v-else-if="scope.row.status === '0'" type="primary">运行中</el-tag>
<el-tag v-else-if="scope.row.status === '1'" type="success">完成</el-tag>
<el-tag v-else-if="scope.row.status === '2'" type="danger">作废</el-tag>
<el-tag v-else-if="scope.row.status === '3'" type="info">终止</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180" show-overflow-tooltip>
<template #header>
<el-icon><Clock /></el-icon>
<span style="margin-left: 4px">创建时间</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="200">
<template #default="scope">
<el-button
icon="View"
link
type="primary"
@click="formDialogRef.openDialog('view', scope.row)">
查看
</el-button>
<el-button
v-if="scope.row.status === '-1'"
icon="Edit"
link
type="primary"
@click="formDialogRef.openDialog('edit', scope.row)">
编辑
</el-button>
<el-button
v-if="scope.row.status === '-1'"
icon="Delete"
link
type="danger"
@click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="state.total > 0"
:total="state.total"
v-model:page="state.page"
v-model:limit="state.limit"
@pagination="getDataList"
/>
</el-card>
</div>
<!-- 编辑新增表单对话框 -->
<FormDialog ref="formDialogRef" @refresh="getDataList" />
</div>
</template>
<script setup lang="ts" name="PurchasingRequisition">
import { ref, reactive, defineAsyncComponent } from 'vue'
import { BasicTableProps, useTable } from "/@/hooks/table";
import { getPage, delObj } from "/@/api/finance/purchasingrequisition";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { List, Document, DocumentCopy, Search, Collection, Money, CircleCheck, InfoFilled, Clock } from '@element-plus/icons-vue'
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义变量内容
const tableRef = ref()
const formDialogRef = ref()
const searchFormRef = ref()
const showSearch = ref(true)
/**
* 定义响应式表格数据
*/
const state: BasicTableProps = reactive<BasicTableProps>({
pageList: getPage,
queryForm: {
purchaseNo: '',
projectName: '',
projectType: '',
status: '',
isCentralized: '',
},
createdIsNeed: true
});
/**
* 使用 useTable 定义表格相关操作
*/
const { getDataList, tableStyle } = useTable(state);
/**
* 重置搜索表单
*/
const handleReset = () => {
searchFormRef.value?.resetFields();
getDataList();
};
/**
* 删除当前行
* @param row - 当前行数据
*/
const handleDelete = async (row: any) => {
try {
await useMessageBox().confirm('确定要删除该记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
} catch {
return;
}
try {
await delObj(row.id);
useMessage().success('删除成功');
getDataList();
} catch (err: any) {
useMessage().error(err.msg || '删除失败');
}
};
</script>
<style scoped lang="scss">
@import '/@/assets/styles/modern-page.scss';
</style>

View File

@@ -82,7 +82,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive } from 'vue'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { fetchList } from '/@/api/professional/professionaluser/professionalpartychange' import { fetchList } from '/@/api/professional/professionaluser/professionalpartychange'
@@ -130,10 +130,7 @@ const resetQuery = () => {
getDataList() getDataList()
} }
// 初始化 // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
onMounted(() => {
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -418,10 +418,9 @@ const loadDictData = async () => {
} }
} }
// 初始化 // 初始化:仅加载下拉字典,表格数据由 useTablecreatedIsNeed 默认 true自动请求
onMounted(async () => { onMounted(async () => {
await loadDictData() await loadDictData()
getDataList()
}) })
</script> </script>

View File

@@ -472,10 +472,9 @@ const loadDictData = async () => {
} }
} }
// 初始化 // 初始化:仅加载下拉字典,表格数据由 useTablecreatedIsNeed 默认 true自动请求
onMounted(async () => { onMounted(async () => {
await loadDictData() await loadDictData()
getDataList()
}) })
</script> </script>

View File

@@ -56,16 +56,16 @@
<el-row> <el-row>
<div class="mb15" style="width: 100%;"> <div class="mb15" style="width: 100%;">
<el-button <el-button
v-auth="'professional_professionalteachercertificaterelation_add'"
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd">
v-if="permissions.professional_professionalteachercertificaterelation_add">
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_teacherbase_export'"
type="warning" type="warning"
plain plain
icon="Download" icon="Download"
v-if="permissions.professional_teacherbase_export"
@click="handleDownLoadWord" @click="handleDownLoadWord"
:loading="exportLoading">导出信息 :loading="exportLoading">导出信息
</el-button> </el-button>
@@ -123,17 +123,19 @@
<el-table-column label="操作" width="280" align="center" fixed="right"> <el-table-column label="操作" width="280" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-auth="'professional_professionalteachercertificaterelation_edit'"
v-if="scope.row.state === '0' || scope.row.state === '-2'"
type="primary" type="primary"
link link
icon="edit-pen" icon="edit-pen"
v-if="permissions.professional_professionalteachercertificaterelation_edit && (scope.row.state === '0' || scope.row.state === '-2')"
@click="handleEdit(scope.row)">编辑 @click="handleEdit(scope.row)">编辑
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteachercertificaterelation_exam'"
v-if="scope.row.canExam"
type="success" type="success"
link link
icon="CircleCheck" icon="CircleCheck"
v-if="permissions.professional_professionalteachercertificaterelation_exam && scope.row.canExam"
@click="changeState(scope.row, 1)">通过 @click="changeState(scope.row, 1)">通过
</el-button> </el-button>
<el-button <el-button
@@ -144,10 +146,11 @@
@click="changeState(scope.row, 1)">部门通过 @click="changeState(scope.row, 1)">部门通过
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteachercertificaterelation_exam'"
v-if="scope.row.canBack"
type="danger" type="danger"
link link
icon="CircleClose" icon="CircleClose"
v-if="permissions.professional_professionalteachercertificaterelation_exam && scope.row.canBack"
@click="changeState(scope.row, -2)">驳回 @click="changeState(scope.row, -2)">驳回
</el-button> </el-button>
<el-button <el-button
@@ -158,10 +161,10 @@
@click="changeState(scope.row, -2)">部门驳回 @click="changeState(scope.row, -2)">部门驳回
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteachercertificaterelation_del'"
type="danger" type="danger"
link link
icon="delete" icon="delete"
v-if="permissions.professional_professionalteachercertificaterelation_del"
style="margin-left: 12px" style="margin-left: 12px"
@click="handleDel(scope.row)">删除 @click="handleDel(scope.row)">删除
</el-button> </el-button>
@@ -192,9 +195,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
@@ -221,19 +222,6 @@ const auditStateOptions: StateOption[] = [
{ value: '0', label: '待审核', type: 'warning', icon: 'fa-regular fa-clock', effect: 'light' } { value: '0', label: '待审核', type: 'warning', icon: 'fa-regular fa-clock', effect: 'light' }
] ]
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -411,10 +399,9 @@ const loadDictData = async () => {
} }
} }
// 初始化 // 初始化:仅加载下拉字典,表格数据由 useTablecreatedIsNeed 默认 true自动请求
onMounted(async () => { onMounted(async () => {
await loadDictData() await loadDictData()
getDataList()
}) })
</script> </script>

View File

@@ -56,10 +56,10 @@
<el-row> <el-row>
<div class="mb15" style="width: 100%;"> <div class="mb15" style="width: 100%;">
<el-button <el-button
v-auth="'professional_professionalteacherhonor_add'"
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd">
v-if="permissions.professional_professionalteacherhonor_add">
</el-button> </el-button>
<el-button <el-button
type="warning" type="warning"
@@ -118,17 +118,19 @@
<el-table-column label="操作" width="280" align="center" fixed="right"> <el-table-column label="操作" width="280" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-auth="'professional_professionalteacherhonor_edit'"
v-if="scope.row.state === '0' || scope.row.state === '-2'"
type="primary" type="primary"
link link
icon="edit-pen" icon="edit-pen"
v-if="permissions.professional_professionalteacherhonor_edit && (scope.row.state === '0' || scope.row.state === '-2')" @click="handleEdit(scope.row)">修改
@click="handleEdit(scope.row)">编辑
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteacherhonor_exam'"
v-if="scope.row.canExam"
type="success" type="success"
link link
icon="CircleCheck" icon="CircleCheck"
v-if="permissions.professional_professionalteacherhonor_exam && scope.row.canExam"
@click="changeState(scope.row, 1)">通过 @click="changeState(scope.row, 1)">通过
</el-button> </el-button>
<el-button <el-button
@@ -139,10 +141,11 @@
@click="changeState(scope.row, 1)">部门通过 @click="changeState(scope.row, 1)">部门通过
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteacherhonor_exam'"
v-if="scope.row.canBack"
type="danger" type="danger"
link link
icon="CircleClose" icon="CircleClose"
v-if="permissions.professional_professionalteacherhonor_exam && scope.row.canBack"
@click="changeState(scope.row, -2)">驳回 @click="changeState(scope.row, -2)">驳回
</el-button> </el-button>
<el-button <el-button
@@ -153,10 +156,10 @@
@click="changeState(scope.row, -2)">部门驳回 @click="changeState(scope.row, -2)">部门驳回
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionalteacherhonor_del'"
type="danger" type="danger"
link link
icon="delete" icon="delete"
v-if="permissions.professional_professionalteacherhonor_del"
style="margin-left: 12px" style="margin-left: 12px"
@click="handleDel(scope.row)">删除 @click="handleDel(scope.row)">删除
</el-button> </el-button>
@@ -187,9 +190,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue' import { ref, reactive, nextTick } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
@@ -199,6 +200,7 @@ import {
examObj, examObj,
delObj delObj
} from '/@/api/professional/professionaluser/professionalteacherhonor' } from '/@/api/professional/professionaluser/professionalteacherhonor'
import { PROFESSIONAL_AUDIT_STATE_OPTIONS } from '/@/config/global'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue')) const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
const AuditState = defineAsyncComponent(() => import('/@/components/AuditState/index.vue')) const AuditState = defineAsyncComponent(() => import('/@/components/AuditState/index.vue'))
@@ -206,19 +208,6 @@ const ProfessionalBackResaon = defineAsyncComponent(() => import('/@/views/profe
const DataForm = defineAsyncComponent(() => import('./form.vue')) const DataForm = defineAsyncComponent(() => import('./form.vue'))
const previewFile = defineAsyncComponent(() => import('/@/components/tools/preview-file.vue')) const previewFile = defineAsyncComponent(() => import('/@/components/tools/preview-file.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -226,13 +215,8 @@ const messageBox = useMessageBox()
// 字典数据 // 字典数据
const { professional_state: professionalState } = useDict('professional_state') const { professional_state: professionalState } = useDict('professional_state')
// 审核状态选项(独立定义,防止其他页面修改时被波及) // 审核状态选项
import type { StateOption } from '/@/components/AuditState/index.vue' const auditStateOptions = PROFESSIONAL_AUDIT_STATE_OPTIONS
const auditStateOptions: StateOption[] = [
{ value: '1', label: '已通过', type: 'success', icon: 'fa-solid fa-circle-check', effect: 'dark' },
{ value: '-2', label: '已驳回', type: 'danger', icon: 'fa-solid fa-circle-xmark', effect: 'dark' },
{ value: '0', label: '待审核', type: 'warning', icon: 'fa-regular fa-clock', effect: 'light' }
]
// 表格引用 // 表格引用
const tableRef = ref() const tableRef = ref()
@@ -379,10 +363,7 @@ const handleDownLoadWord = async () => {
} }
} }
// 初始化 // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
onMounted(() => {
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -83,7 +83,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive } from 'vue'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
@@ -145,10 +145,7 @@ const doPrint = (row: any) => {
window.open(routeData.href, '_blank') window.open(routeData.href, '_blank')
} }
// 初始化 // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
onMounted(() => {
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionalteachertype_add"> v-auth="'professional_professionalteachertype_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionalteachertype_edit" v-auth="'professional_professionalteachertype_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionalteachertype_del" v-auth="'professional_professionalteachertype_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -63,7 +63,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="600px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalteachertype' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalteachertype'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,7 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionalteachingmaterialconfig_add"> v-auth="'professional_professionalteachingmaterialconfig_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionalteachingmaterialconfig_edit" v-auth="'professional_professionalteachingmaterialconfig_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionalteachingmaterialconfig_del" v-auth="'professional_professionalteachingmaterialconfig_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalteachingmaterialconfig' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalteachingmaterialconfig'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,7 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionaltitlelevelconfig_add"> v-auth="'professional_professionaltitlelevelconfig_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionaltitlelevelconfig_edit" v-auth="'professional_professionaltitlelevelconfig_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionaltitlelevelconfig_del" v-auth="'professional_professionaltitlelevelconfig_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltitlelevelconfig' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltitlelevelconfig'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,6 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog v-model="dialogVisible" title="编辑职称" width="600px" append-to-body :close-on-click-modal="false" destroy-on-close> <el-dialog v-model="dialogVisible" title="修改职称" width="600px" append-to-body :close-on-click-modal="false" destroy-on-close>
<div v-if="showForm"> <div v-if="showForm">
<el-form <el-form
ref="formRef" ref="formRef"

View File

@@ -88,17 +88,17 @@
<el-row> <el-row>
<div class="mb15" style="width: 100%;"> <div class="mb15" style="width: 100%;">
<el-button <el-button
v-auth="'professional_professionaltitlerelation_add'"
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd">
v-if="permissions.professional_professionaltitlerelation_add">
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_teacherbase_export'"
class="ml10" class="ml10"
type="warning" type="warning"
plain plain
icon="Download" icon="Download"
v-if="permissions.professional_teacherbase_export"
@click="handleDownLoadWord" @click="handleDownLoadWord"
:loading="exportLoading">导出信息 :loading="exportLoading">导出信息
</el-button> </el-button>
@@ -162,45 +162,50 @@
<el-table-column label="操作" width="280" align="center" fixed="right"> <el-table-column label="操作" width="280" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-auth="'professional_professionaltitlerelation_edit'"
v-if="scope.row.state === '0' || scope.row.state === '-2'"
type="primary" type="primary"
link link
icon="edit-pen" icon="edit-pen"
v-if="permissions.professional_professionaltitlerelation_edit && (scope.row.state === '0' || scope.row.state === '-2')" @click="handleEdit(scope.row)">修改
@click="handleEdit(scope.row)">编辑
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionaltitlerelation_exam'"
v-if="scope.row.canExam"
type="success" type="success"
link link
icon="CircleCheck" icon="CircleCheck"
v-if="permissions.professional_professionaltitlerelation_exam && scope.row.canExam"
@click="changeState(scope.row, 1)">通过 @click="changeState(scope.row, 1)">通过
</el-button> </el-button>
<el-button <el-button
type="success" type="success"
link link
icon="CircleCheck" icon="CircleCheck"
v-if="permissions.professional_professionaltitlerelation_exam && scope.row.canDeptExam" v-auth="'professional_professionaltitlerelation_exam'"
v-if="scope.row.canDeptExam"
@click="changeState(scope.row, 1)">部门通过 @click="changeState(scope.row, 1)">部门通过
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionaltitlerelation_exam'"
v-if="scope.row.canBack"
type="danger" type="danger"
link link
icon="CircleClose" icon="CircleClose"
v-if="permissions.professional_professionaltitlerelation_exam && scope.row.canBack"
@click="changeState(scope.row, -2)">驳回 @click="changeState(scope.row, -2)">驳回
</el-button> </el-button>
<el-button <el-button
type="danger" type="danger"
link link
v-auth="'professional_professionaltitlerelation_exam'"
icon="CircleClose" icon="CircleClose"
v-if="permissions.professional_professionaltitlerelation_exam && scope.row.canDeptBack" v-if="scope.row.canDeptBack"
@click="changeState(scope.row, -2)">部门驳回 @click="changeState(scope.row, -2)">部门驳回
</el-button> </el-button>
<el-button <el-button
v-auth="'professional_professionaltitlerelation_del'"
type="danger" type="danger"
link link
icon="delete" icon="delete"
v-if="permissions.professional_professionaltitlerelation_del"
style="margin-left: 12px" style="margin-left: 12px"
@click="handleDel(scope.row)">删除 @click="handleDel(scope.row)">删除
</el-button> </el-button>
@@ -232,9 +237,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue' import { ref, reactive, onMounted, nextTick } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
@@ -258,18 +261,6 @@ const ProfessionalBackResaon = defineAsyncComponent(() => import('/@/views/profe
const previewFile = defineAsyncComponent(() => import('/@/components/tools/preview-file.vue')) const previewFile = defineAsyncComponent(() => import('/@/components/tools/preview-file.vue'))
// 使用 Pinia store // 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -466,11 +457,9 @@ const loadDictData = async () => {
} }
} }
// 初始化 // 初始化:仅加载下拉字典,表格数据由 useTable 在 createdIsNeed: true 时自动请求
onMounted(async () => { onMounted(async () => {
await loadDictData() await loadDictData()
dataFormRef.value?.init()
getDataList()
}) })
</script> </script>

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionaltopiclevelconfig_add"> v-auth="'professional_professionaltopiclevelconfig_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionaltopiclevelconfig_edit" v-auth="'professional_professionaltopiclevelconfig_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionaltopiclevelconfig_del" v-auth="'professional_professionaltopiclevelconfig_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -63,7 +63,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="600px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltopiclevelconfig' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltopiclevelconfig'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,6 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionaltopicsourceconfig_add"> v-auth="'professional_professionaltopicsourceconfig_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionaltopicsourceconfig_edit" v-auth="'professional_professionaltopicsourceconfig_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionaltopicsourceconfig_del" v-auth="'professional_professionaltopicsourceconfig_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -63,7 +63,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="600px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltopicsourceconfig' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionaltopicsourceconfig'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,6 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_worktype_add"> v-auth="'professional_worktype_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -31,14 +31,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_worktype_edit" v-auth="'professional_worktype_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_worktype_del" v-auth="'professional_worktype_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -59,7 +59,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="600px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -91,27 +91,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalworktype' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/professionalworktype'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -203,7 +188,6 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg)
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_professionalyearbounds_add"> v-auth="'professional_professionalyearbounds_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -46,14 +46,14 @@
<el-table-column label="操作" min-width="150" align="center" fixed="right"> <el-table-column label="操作" min-width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_professionalyearbounds_edit" v-auth="'professional_professionalyearbounds_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_professionalyearbounds_del" v-auth="'professional_professionalyearbounds_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -74,7 +74,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="800px" width="800px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -175,29 +175,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/salaries/professionalyearbounds' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/salaries/professionalyearbounds'
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue')) const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -317,7 +302,7 @@ const handleSubmit = async () => {
dialogVisible.value = false dialogVisible.value = false
getDataList(false) // 提交后保持当前页 getDataList(false) // 提交后保持当前页
} catch (error: any) { } catch (error: any) {
message.error(error.msg) // 错误处理已在数据请求层统一处理,此处不需要提示
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -72,7 +72,7 @@
<el-table-column label="操作" min-width="80" align="center" fixed="right"> <el-table-column label="操作" min-width="80" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_salaryexportrecord_del" v-auth="'professional_salaryexportrecord_del'"
icon="delete" icon="delete"
link link
type="primary" type="primary"
@@ -93,26 +93,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { fetchList, delObj } from '/@/api/professional/salaries/salaryexportrecord' import { fetchList, delObj } from '/@/api/professional/salaries/salaryexportrecord'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -169,7 +154,7 @@ const handleDel = (row: any) => {
message.success('删除成功') message.success('删除成功')
getDataList(false) // 删除后保持当前页 getDataList(false) // 删除后保持当前页
} catch (error: any) { } catch (error: any) {
message.error(error.msg) // 错误处理已在数据请求层统一处理,此处不需要提示
} }
}).catch(() => { }).catch(() => {
// 用户取消 // 用户取消

View File

@@ -27,7 +27,7 @@
</template> </template>
<el-button <el-button
size="small" size="small"
v-if="permissions.professional_salary_import" v-auth="'teacher_award_import'"
type="primary">选择文件 type="primary">选择文件
</el-button> </el-button>
</el-upload> </el-upload>
@@ -45,8 +45,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { Session } from '/@/utils/storage' import { Session } from '/@/utils/storage'
import request from '/@/utils/request' import request from '/@/utils/request'
@@ -56,19 +54,6 @@ const emit = defineEmits<{
(e: 'refreshData'): void (e: 'refreshData'): void
}>() }>()
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 // 消息提示
const message = useMessage() const message = useMessage()

View File

@@ -55,7 +55,7 @@
type="primary" type="primary"
plain plain
icon="UploadFilled" icon="UploadFilled"
v-if="permissions.teacher_award_import" v-auth="'teacher_award_import'"
@click="handleImportBaseSalary">绩效导入 @click="handleImportBaseSalary">绩效导入
</el-button> </el-button>
</div> </div>
@@ -107,25 +107,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { fetchList } from '/@/api/professional/salaries/teacherawardtax' import { fetchList } from '/@/api/professional/salaries/teacherawardtax'
import ImportAwardTax from './importAwardTax.vue' const ImportAwardTax = defineAsyncComponent(() => import('./importAwardTax.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 表格引用 // 表格引用
const tableRef = ref() const tableRef = ref()

View File

@@ -1492,7 +1492,7 @@
import {updateStatus} from '/@/api/professional/professionalstatuslock' import {updateStatus} from '/@/api/professional/professionalstatuslock'
import {resetPassWord} from "/@/api/professional/professionaluser/teacherbase" import {resetPassWord} from "/@/api/professional/professionaluser/teacherbase"
// 组件配置已不再需要(已从 avue-crud 迁移到 el-table // 组件配置已不再需要(已从 avue-crud 迁移到 el-table
import authImg from "/@/components/tools/auth-img.vue" const authImg = defineAsyncComponent(() => import("/@/components/tools/auth-img.vue"))
// 导入工具 // 导入工具
import { Session } from '/@/utils/storage' import { Session } from '/@/utils/storage'

View File

@@ -90,19 +90,19 @@
type="primary" type="primary"
plain plain
icon="UploadFilled" icon="UploadFilled"
v-if="permissions.professional_salary_import" v-auth="'professional_salary_import'"
@click="handleImportBaseSalary">工资条导入 @click="handleImportBaseSalary">工资条导入
</el-button> </el-button>
<el-button <el-button
icon="View" icon="View"
class="ml10" class="ml10"
v-if="permissions.professional_seach_auth" v-auth="'professional_seach_auth'"
@click="canSearch(1)">设置可查询 @click="canSearch(1)">设置可查询
</el-button> </el-button>
<el-button <el-button
icon="Hide" icon="Hide"
class="ml10" class="ml10"
v-if="permissions.professional_seach_auth" v-auth="'professional_seach_auth'"
@click="canSearch(0)">设置不可查询 @click="canSearch(0)">设置不可查询
</el-button> </el-button>
<el-button <el-button
@@ -110,7 +110,7 @@
plain plain
icon="Delete" icon="Delete"
class="ml10" class="ml10"
v-if="permissions.professional_professionalsalaries_del" v-auth="'professional_professionalsalaries_del'"
@click="delbatch">批量删除 @click="delbatch">批量删除
</el-button> </el-button>
</div> </div>
@@ -186,33 +186,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { fetchList, delBatch, setCanSearch } from '/@/api/professional/salaries/teacherpayslip' import { fetchList, delBatch, setCanSearch } from '/@/api/professional/salaries/teacherpayslip'
import { checkAuth } from '/@/api/professional/salaries/teachersalary' import { checkAuth } from '/@/api/professional/salaries/teachersalary'
import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig' import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig'
import SalaryInfo from './salaryInfo.vue' const SalaryInfo = defineAsyncComponent(() => import('./salaryInfo.vue'))
import ImportBaseSalary from './importBaseSalary.vue' const ImportBaseSalary = defineAsyncComponent(() => import('./importBaseSalary.vue'))
import ExportBaseSalary from './exportBaseSalary.vue' const ExportBaseSalary = defineAsyncComponent(() => import('./exportBaseSalary.vue'))
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue')) const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
@@ -339,7 +325,7 @@ const delbatch = () => {
getDataList(false) // 删除后保持当前页 getDataList(false) // 删除后保持当前页
} }
} catch (error: any) { } catch (error: any) {
message.error(error?.msg || '删除失败') // 错误处理已在数据请求层统一处理,此处不需要提示
} }
}).catch(() => { }).catch(() => {
// 用户取消 // 用户取消
@@ -359,7 +345,7 @@ const canSearch = (val: number) => {
message.success("设置成功") message.success("设置成功")
getDataList(false) // 设置后保持当前页 getDataList(false) // 设置后保持当前页
} catch (error: any) { } catch (error: any) {
message.error(error?.msg || '设置失败') // 错误处理已在数据请求层统一处理,此处不需要提示
} }
}).catch(() => { }).catch(() => {
// 用户取消 // 用户取消

View File

@@ -96,7 +96,7 @@
type="primary" type="primary"
plain plain
icon="UploadFilled" icon="UploadFilled"
v-if="permissions.professional_salary_import" v-auth="'professional_salary_import'"
@click="handleImportBaseSalary">人事薪资导入 @click="handleImportBaseSalary">人事薪资导入
</el-button> </el-button>
<el-button <el-button
@@ -104,7 +104,7 @@
plain plain
icon="Download" icon="Download"
class="ml10" class="ml10"
v-if="permissions.professional_salary_finance_import" v-auth="'professional_salary_finance_import'"
@click="handleExportSalart">薪资导出 @click="handleExportSalart">薪资导出
</el-button> </el-button>
<el-button <el-button
@@ -112,19 +112,19 @@
plain plain
icon="UploadFilled" icon="UploadFilled"
class="ml10" class="ml10"
v-if="permissions.professional_salary_finance_import" v-auth="'professional_salary_finance_import'"
@click="handleImportTaxSalary">税金导入 @click="handleImportTaxSalary">税金导入
</el-button> </el-button>
<el-button <el-button
icon="View" icon="View"
class="ml10" class="ml10"
v-if="permissions.professional_seach_auth" v-auth="'professional_seach_auth'"
@click="canSearch(1)">设置可查询 @click="canSearch(1)">设置可查询
</el-button> </el-button>
<el-button <el-button
icon="Hide" icon="Hide"
class="ml10" class="ml10"
v-if="permissions.professional_seach_auth" v-auth="'professional_seach_auth'"
@click="canSearch(0)">设置不可查询 @click="canSearch(0)">设置不可查询
</el-button> </el-button>
<el-button <el-button
@@ -132,7 +132,7 @@
plain plain
icon="Delete" icon="Delete"
class="ml10" class="ml10"
v-if="permissions.professional_professionalsalaries_del" v-auth="'professional_professionalsalaries_del'"
@click="delbatch">批量删除 @click="delbatch">批量删除
</el-button> </el-button>
</div> </div>
@@ -208,33 +208,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { fetchList, delBatch, setCanSearch, checkAuth } from '/@/api/professional/salaries/teachersalary' import { fetchList, delBatch, setCanSearch, checkAuth } from '/@/api/professional/salaries/teachersalary'
import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig' import { getStationLevelList } from '/@/api/professional/professionalstationlevelconfig'
import SalaryInfo from './salaryInfo.vue' const SalaryInfo = defineAsyncComponent(() => import('./salaryInfo.vue'))
import ImportBaseSalary from './importBaseSalary.vue' const ImportBaseSalary = defineAsyncComponent(() => import('./importBaseSalary.vue'))
const ExportBaseSalary = defineAsyncComponent(() => import('./exportBaseSalary.vue'))
const ImportTaxSalary = defineAsyncComponent(() => import('./importTaxSalary.vue'))
const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue')) const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
import ExportBaseSalary from './exportBaseSalary.vue'
import ImportTaxSalary from './importTaxSalary.vue'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
@@ -396,7 +381,7 @@ const canSearch = (val: number) => {
message.success("设置成功") message.success("设置成功")
getDataList(false) // 设置后保持当前页 getDataList(false) // 设置后保持当前页
} catch (error: any) { } catch (error: any) {
message.error(error?.msg || '设置失败') // 错误处理已在数据请求层统一处理,此处不需要提示
} }
}).catch(() => { }).catch(() => {
// 用户取消 // 用户取消

View File

@@ -341,7 +341,7 @@ const searchUserInfo = async () => {
message.success('查询成功') message.success('查询成功')
} }
} catch (error: any) { } catch (error: any) {
message.error(error?.msg || '查询失败') // 错误处理已在数据请求层统一处理,此处不需要提示
} finally { } finally {
baseLoading.value = false baseLoading.value = false
} }

View File

@@ -8,7 +8,7 @@
type="primary" type="primary"
icon="FolderAdd" icon="FolderAdd"
@click="handleAdd" @click="handleAdd"
v-if="permissions.professional_typeofworkconfig_add"> v-auth="'professional_typeofworkconfig_add'">
</el-button> </el-button>
</div> </div>
</el-row> </el-row>
@@ -35,14 +35,14 @@
<el-table-column label="操作" width="150" align="center" fixed="right"> <el-table-column label="操作" width="150" align="center" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.professional_typeofworkconfig_edit" v-auth="'professional_typeofworkconfig_edit'"
icon="edit-pen" icon="edit-pen"
link link
type="primary" type="primary"
@click="handleEdit(scope.row)">修改 @click="handleEdit(scope.row)">修改
</el-button> </el-button>
<el-button <el-button
v-if="permissions.professional_typeofworkconfig_del" v-auth="'professional_typeofworkconfig_del'"
icon="delete" icon="delete"
link link
type="danger" type="danger"
@@ -63,7 +63,7 @@
<!-- 新增/编辑弹窗 --> <!-- 新增/编辑弹窗 -->
<el-dialog <el-dialog
v-model="dialogVisible" v-model="dialogVisible"
:title="form.id ? '编辑' : '新增'" :title="form.id ? '修改' : '新增'"
width="600px" width="600px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close destroy-on-close
@@ -114,27 +114,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed } from 'vue' import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message' import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/typeofworkconfig' import { fetchList, addObj, putObj, delObj } from '/@/api/professional/rsbase/typeofworkconfig'
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -235,7 +220,7 @@ const handleSubmit = async () => {
getDataList() getDataList()
} catch (error: any) { } catch (error: any) {
// 处理业务错误 // 处理业务错误
message.error(error.msg) // 错误处理已在数据请求层统一处理,此处不需要提示
} finally { } finally {
submitLoading.value = false submitLoading.value = false
} }

View File

@@ -167,7 +167,7 @@
</template> </template>
<script setup lang="ts" name="recruitstudentplan"> <script setup lang="ts" name="recruitstudentplan">
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, computed } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo' import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
@@ -312,9 +312,7 @@ const handleSubmit = async () => {
}) })
} }
onMounted(() => { // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -113,7 +113,7 @@
</template> </template>
<script setup lang="ts" name="recruitstudentplandegreeofeducation"> <script setup lang="ts" name="recruitstudentplandegreeofeducation">
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, computed } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo' import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
@@ -242,9 +242,7 @@ const handleSubmit = async () => {
}) })
} }
onMounted(() => { // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -307,9 +307,9 @@ const resetQuery = () => {
getDataList(); getDataList();
}; };
// 表格数据由 useTablecreatedIsNeed 默认 true自动请求onMounted 仅执行 init
onMounted(() => { onMounted(() => {
init(); init();
getDataList();
}); });
</script> </script>

View File

@@ -97,7 +97,7 @@
</template> </template>
<script setup lang="ts" name="recruitstudentsignupturnovermoneychange"> <script setup lang="ts" name="recruitstudentsignupturnovermoneychange">
import { ref, reactive, computed, onMounted, defineAsyncComponent, nextTick } from 'vue' import { ref, reactive, computed, defineAsyncComponent, nextTick } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo' import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
@@ -182,9 +182,7 @@ const handleDel = async (row: any) => {
} }
} }
onMounted(() => { // 表格数据由 useTablecreatedIsNeed 默认 true在挂载时自动请求
getDataList()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -19,7 +19,7 @@
clearable clearable
filterable filterable
style="width: 200px"> style="width: 200px">
<el-option <el-option
v-for="item in schoolYearList" v-for="item in schoolYearList"
:key="item.year" :key="item.year"
:label="item.year" :label="item.year"