我发起的变更列表部分

This commit is contained in:
2026-09-18 17:30:49 +08:00
parent f97e137f85
commit ace1401089
3 changed files with 148 additions and 51 deletions
+145 -49
View File
@@ -3,6 +3,7 @@ import { ref, computed, onMounted } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
import { systemConfigApi } from '@/service/api/system';
import { changeLedgerListApi } from '@/service/api/changeLedger';
const { routerPushByKey } = useRouterPush();
@@ -17,7 +18,7 @@ const kw = ref("");
const typeFilter = ref("全部");
const statusFilter = ref("全部");
const durFilter = ref("全部");
const period = ref<string>("近一年");
const customFrom = ref<any>(null);
const customTo = ref<any>(null);
const sort = ref<{ k: string; dir: "asc" | "desc" }>({ k: "applyTime", dir: "desc" });
@@ -70,22 +71,7 @@ const finalRows = computed(() => {
default: return rows.value;
}
});
const TYPE_FILTERS = ["全部", "工艺", "设备", "管理"];
const DUR_FILTERS = ["全部", "永久", "临时"];
const PERIOD_FILTERS = ["近一年", "近半年", "近三个月", "近一个月", "自定义"];
const STATUS_FILTERS = ["全部", "审批中", "已批准", "实施中", "待PSSR", "待验收", "待关闭", "已关闭"];
const sortVal = computed({
get: () => `${sort.value.k}-${sort.value.dir}`,
set: (v: string) => { const [k, dir] = v.split("-") as [string, "asc" | "desc"]; sort.value = { k, dir }; },
});
const SORT_OPTS = [
{ label: "申请时间 · 最新", value: "applyTime-desc" },
{ label: "申请时间 · 最早", value: "applyTime-asc" },
{ label: "计划投用 · 最近", value: "planUse-asc" },
{ label: "计划投用 · 最晚", value: "planUse-desc" },
{ label: "状态更新 · 最新", value: "statusTime-desc" },
{ label: "状态更新 · 最早", value: "statusTime-asc" },
];
interface LedgerExtra {
special?: ("延期" | "临时转永久" | "未实施" | "未投用")[];
actualUse?: string; planRestore?: string; extRestore?: string; closeTime?: string;
@@ -433,17 +419,6 @@ const doOp = (r: any, act: string) => {
window.$message?.info(`演示:下载 ${r.id} 变更申请表 / 归档包(PDF`);
};
// 重置
const reset = () => {
dept.value = "全部组织"; openOnly.value = false; kw.value = ""; typeFilter.value = "全部"; statusFilter.value = "全部";
durFilter.value = "全部"; period.value = "近一年"; customFrom.value = null; customTo.value = null;
sort.value = { k: "applyTime", dir: "desc" };
window.$message?.success("筛选条件已重置");
};
// 导出台账
const exportChanges = () => {
window.$message?.success(`演示:导出台账 Excel(当前筛选 ${finalRows.value.length} 条)`);
}
// 撤回弹框取消
const revokeCancel = () => {
ledgerAct.value = null;
@@ -464,23 +439,126 @@ const loading = ref<boolean>(false);
// 筛选条件
const formInfo = ref<any>({
kw: '',
type: 0,
level: 0,
duration: 0,
status: [],
type: null,
level: null,
duration: null,
status: '',//英文逗号隔开
org_id: 1,
apply_time_start: null,
apply_time_end: null,
self: 1,
self: '1',
});
const pagination = ref<{page: number, pageSize: number, itemCount: number}>({
page: 1,
pageSize: 3,
pageSize: 20,
itemCount: 0,
})
// 变更类型列表
const typeList = ref<any[]>([{ label: "全部", value: null }]);
// 变更等级列表
const levelList = ref<any[]>([{ label: "全部", value: null }]);
// 状态选项
const STATUS_OPTIONS = [
{ label: "全部", value: "" },
{ label: "审批中", value: "APPROVING" },
{ label: "待实施", value: "APPROVED" },
{ label: "待验收", value: "IMPLEMENTED" },
{ label: "待关闭", value: "ACCEPTED" },
{ label: "已关闭", value: "CLOSED" },
{ label: "已撤回", value: "WITHDRAWN" },
{ label: "已驳回", value: "REJECTED" },
];
// 排序选项
const SORT_OPTS = [
{ label: "申请时间 · 最新", value: "apply_time,desc" },
{ label: "申请时间 · 最早", value: "apply_time,asc" },
{ label: "计划投用 · 最新", value: "plan_use_date,desc" },
{ label: "计划投用 · 最早", value: "plan_use_date,asc" },
{ label: "状态更新 · 最新", value: "status_changed_at,desc" },
{ label: "状态更新 · 最早", value: "status_changed_at,asc" },
];
// 时限选项
const DUR_OPTIONS = [
{ label: "全部", value: null },
{ label: "永久", value: 1 },
{ label: "临时", value: 2 }
];
// 时间选项
const TIME_OPTIONS = [
{ label: "近一年", value: 'year' },
{ label: "近半年", value: 'half_year' },
{ label: "近三个月", value: 'quarter' },
{ label: "近一个月", value: 'month' },
{ label: "自定义", value: 'custom' },
];
// 当前选中时间范围
const period = ref<string>("year");
// 是否显示全部
const isAll = ref<boolean>(true);
// 列表
const list = ref<any[]>([]);
// 重置
const reset = () => {
formInfo.value.kw = '';
formInfo.value.type = null;
formInfo.value.level = null;
formInfo.value.duration = null;
formInfo.value.status = '';
formInfo.value.sort = '';
period.value = 'year';
isAll.value = true;
window.$message?.success("筛选条件已重置");
};
// 导出台账
const exportChanges = () => {
window.$message?.info('还差接口');
}
// 显示全部改变
const showAll = () => {
isAll.value = !isAll.value;
if(isAll.value){
formInfo.value.status = '';
}else{
formInfo.value.status = 'APPROVING,APPROVED,IMPLEMENTED,ACCEPTED,WITHDRAWN,REJECTED';
}
pagination.value.page = 1;
getList();
}
// 类型选择
const typeChoose = (val:any) => {
formInfo.value.type = val;
pagination.value.page = 1;
getList();
}
// 时限选择
const durChoose = (val:any) => {
formInfo.value.duration = val;
pagination.value.page = 1;
getList();
}
// 时间范围选择
const timeChoose = (val:string) => {
period.value = val;
pagination.value.page = 1;
getList();
}
// 状态选择
const statusChoose = (val:string) => {
formInfo.value.status = val;
pagination.value.page = 1;
getList();
}
// 排序选择
const sortChoose = (val:string) => {
formInfo.value.sort = val;
pagination.value.page = 1;
getList();
}
// 分页改变
const pageChange = (page: number) => {
pagination.value.page = page;
@@ -509,8 +587,25 @@ const getList = async () => {
}
loading.value = false;
}
// 获取配置
const getConfig = async () => {
const {data,error} = await systemConfigApi();
if(!error){
// 解析 变更类型设置
const changeTypeGroup = data.find((group:{group_key:string}) => group.group_key === 'change_type');
if (changeTypeGroup) {
typeList.value = typeList.value.concat(changeTypeGroup.items);
}
// 解析 变更等级设置
const changeLevelGroup = data.find((group:{group_key:string}) => group.group_key === 'change_level');
if (changeLevelGroup) {
levelList.value = levelList.value.concat(changeLevelGroup.items);
}
}
}
onMounted(() => {
getConfig();
getList();
});
</script>
@@ -529,22 +624,23 @@ onMounted(() => {
<Icon icon="akar-icons:file" class="size-16px" :style="{ color: themeStore.themeColor }" /> 全部变更
<span class="rounded bg-slate-100 px-1.5 text-xs text-slate-500">{{ finalRows.length }}</span>
</span>
<NSelect size="small" class="!w-32" :value="dept" :options="deptOpts" @update:value="(v: string) => dept = v" />
<NSelect size="small" class="!w-32" :value="formInfo.org_id" :options="deptOpts" @update:value="(v: string) => formInfo.org_id = v" />
<NRadio
size="small"
:checked="!openOnly"
:value="false"
:checked="isAll"
:value="true"
name="显示全部"
@change="openOnly = false"
:on-update:checked="showAll"
>
显示全部
</NRadio>
<NRadio
size="small"
:checked="openOnly"
:value="true"
:checked="!isAll"
:value="false"
name="显示未关闭"
@change="openOnly = true"
:on-update:checked="showAll"
>
显示未关闭
</NRadio>
@@ -570,30 +666,30 @@ onMounted(() => {
<div class="flex items-center gap-x-4">
<p class="flex items-center gap-1.5 min-h-28px">
<span class="text-xs text-slate-400">类型</span>
<NButton size="tiny" round v-for="t in TYPE_FILTERS" :key="t" :ghost="typeFilter === t ? false : true" :type="typeFilter === t ? 'primary' : 'default'" @click="typeFilter = t">{{ t }}</NButton>
<NButton size="tiny" round v-for="t in typeList" :key="t.label" :ghost="formInfo.type === t.value ? false : true" :type="formInfo.type === t.value ? 'primary' : 'default'" @click="typeChoose(t.value)">{{ t.label }}</NButton>
</p>
<p class="flex items-center gap-1.5 min-h-28px">
<span class="text-xs text-slate-400">时限</span>
<NButton size="tiny" round v-for="d in DUR_FILTERS" :key="d" :ghost="durFilter === d ? false : true" :type="durFilter === d ? 'primary' : 'default'" @click="durFilter = d">{{ d }}</NButton>
<NButton size="tiny" round v-for="d in DUR_OPTIONS" :key="d.label" :ghost="formInfo.duration === d.value ? false : true" :type="formInfo.duration === d.value ? 'primary' : 'default'" @click="durChoose(d.value)">{{ d.label }}</NButton>
</p>
<p class="flex flex-wrap items-center gap-1.5 min-h-28px">
<span class="text-xs text-slate-400">时间</span>
<NButton size="tiny" round v-for="p in PERIOD_FILTERS" :key="p" :ghost="period === p ? false : true" :type="period === p ? 'primary' : 'default'" @click="period = p">{{ p }}</NButton>
<span v-if="period === '自定义'" class="flex items-center gap-1">
<NDatePicker v-model:value="customFrom" type="date" size="small" class="w-130px" />
<NButton size="tiny" round v-for="p in TIME_OPTIONS" :key="p.value" :ghost="period === p.value ? false : true" :type="period === p.value ? 'primary' : 'default'" @click="timeChoose(p.value)">{{ p.label }}</NButton>
<span v-if="period === 'custom'" class="flex items-center gap-1">
<NDatePicker v-model:value="formInfo.apply_time_start" type="date" size="small" class="w-130px" />
<span class="text-xs text-slate-400"></span>
<NDatePicker v-model:value="customTo" type="date" size="small" class="w-130px" />
<NDatePicker v-model:value="formInfo.apply_time_end" type="date" size="small" class="w-130px" />
</span>
</p>
</div>
<div class="flex items-center gap-x-4">
<p class="flex flex-wrap items-center gap-1.5 min-h-28px">
<span class="text-xs text-slate-400">状态</span>
<NButton size="tiny" round v-for="s in STATUS_FILTERS" :key="s" :ghost="statusFilter === s ? false : true" :type="statusFilter === s ? 'primary' : 'default'" @click="statusFilter = s">{{ s }}</NButton>
<NButton size="tiny" round v-for="s in STATUS_OPTIONS" :key="s.value" :ghost="formInfo.status === s.value ? false : true" :type="formInfo.status === s.value ? 'primary' : 'default'" @click="statusChoose(s.value)">{{ s.label }}</NButton>
</p>
<p class="ml-auto flex items-center gap-1.5 min-h-28px">
<span class="text-xs text-slate-400">排序</span>
<NSelect size="small" class="!w-36" v-model:value="sortVal" :options="SORT_OPTS" />
<NSelect size="small" class="!w-36" v-model:value="formInfo.sort" :options="SORT_OPTS" :on-update:value="sortChoose" />
</p>
</div>
</div>
+2 -1
View File
@@ -312,7 +312,8 @@ const getConfig = async () => {
const getTemplateConfig = async () => {
const {data,error} = await templateListApi();
if(!error){
templateList.value = data;
const result = data.filter((item:any) => item.type === 1);
templateList.value = result;
}
}
// 获取组织列表
+1 -1
View File
@@ -126,7 +126,7 @@ onMounted(() => {
</template>
<div v-else class="rounded-lg border border-dashed bg-white py-12 text-center scroll2">
<div class="text-sm text-slate-400">暂无草稿</div>
<div class="mt-1 text-xs text-slate-300">在变更申请页点击右保存即可将当前内容存为草稿</div>
<div class="mt-1 text-xs text-slate-300">发起变更页点击右保存即可将当前内容存为草稿</div>
</div>
</NSpin>
</NCard>