|
@@ -1,19 +1,48 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div v-loading="pageLoading" class="app-container" :element-loading-text="loadingText">
|
|
<div v-loading="pageLoading" class="app-container" :element-loading-text="loadingText">
|
|
|
- <PageSearch
|
|
|
|
|
- ref="searchRef"
|
|
|
|
|
- :search-config="searchConfig"
|
|
|
|
|
- @query-click="handleQueryClick"
|
|
|
|
|
- @reset-click="handleResetClick"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <!-- 顶部分类标签栏 -->
|
|
|
|
|
+ <div class="category-tabs">
|
|
|
|
|
+ <div class="category-tabs__nav">
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ v-for="tab in categoryTabs"
|
|
|
|
|
+ :key="tab.key"
|
|
|
|
|
+ :type="activeCategory === tab.key ? 'primary' : 'default'"
|
|
|
|
|
+ :icon="tab.icon"
|
|
|
|
|
+ @click="handleCategoryChange(tab.key)"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ tab.label }}
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 搜索栏和场景选择 -->
|
|
|
|
|
+ <div class="search-bar">
|
|
|
|
|
+ <div class="search-bar__scene">
|
|
|
|
|
+ <span class="search-bar__label">场景:</span>
|
|
|
|
|
+ <el-radio-group v-model="sceneValue" class="scene-radio-group">
|
|
|
|
|
+ <el-radio
|
|
|
|
|
+ v-for="scene in currentScenes"
|
|
|
|
|
+ :key="scene.value"
|
|
|
|
|
+ :label="scene.value"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ scene.label }}
|
|
|
|
|
+ </el-radio>
|
|
|
|
|
+ </el-radio-group>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="search-bar__right">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="searchName"
|
|
|
|
|
+ placeholder="制度名称搜索"
|
|
|
|
|
+ class="search-bar__input"
|
|
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
|
|
+ />
|
|
|
|
|
+ <el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
|
|
|
+ <el-button type="success" @click="handleOpenDialog('create')">新增制度</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
<PageContent ref="contentRef" :content-config="contentConfig">
|
|
<PageContent ref="contentRef" :content-config="contentConfig">
|
|
|
<template #toolbar="{ toolbarRight, onToolbar, removeIds, cols }">
|
|
<template #toolbar="{ toolbarRight, onToolbar, removeIds, cols }">
|
|
|
- <CrudToolbarLeft
|
|
|
|
|
- :remove-ids="removeIds"
|
|
|
|
|
- :perm-create="['module_payment:institution:create']"
|
|
|
|
|
- @add="handleOpenDialog('create')"
|
|
|
|
|
- />
|
|
|
|
|
<div class="data-table__toolbar--right">
|
|
<div class="data-table__toolbar--right">
|
|
|
<CrudToolbarRight :buttons="toolbarRight" :cols="cols" :on-toolbar="onToolbar" />
|
|
<CrudToolbarRight :buttons="toolbarRight" :cols="cols" :on-toolbar="onToolbar" />
|
|
|
</div>
|
|
</div>
|
|
@@ -38,14 +67,6 @@
|
|
|
min-width="55"
|
|
min-width="55"
|
|
|
align="center"
|
|
align="center"
|
|
|
/>
|
|
/>
|
|
|
- <el-table-column
|
|
|
|
|
- v-if="contentCols.find((col) => col.prop === 'institution_id')?.show"
|
|
|
|
|
- key="institution_id"
|
|
|
|
|
- label="制度ID"
|
|
|
|
|
- prop="institution_id"
|
|
|
|
|
- min-width="150"
|
|
|
|
|
- show-overflow-tooltip
|
|
|
|
|
- />
|
|
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
v-if="contentCols.find((col) => col.prop === 'name')?.show"
|
|
v-if="contentCols.find((col) => col.prop === 'name')?.show"
|
|
|
key="name"
|
|
key="name"
|
|
@@ -54,6 +75,14 @@
|
|
|
min-width="150"
|
|
min-width="150"
|
|
|
show-overflow-tooltip
|
|
show-overflow-tooltip
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ v-if="contentCols.find((col) => col.prop === 'valid_period')?.show"
|
|
|
|
|
+ key="valid_period"
|
|
|
|
|
+ label="制度有效期"
|
|
|
|
|
+ prop="valid_period"
|
|
|
|
|
+ min-width="150"
|
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
|
+ />
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
v-if="contentCols.find((col) => col.prop === 'expense_type')?.show"
|
|
v-if="contentCols.find((col) => col.prop === 'expense_type')?.show"
|
|
|
key="expense_type"
|
|
key="expense_type"
|
|
@@ -68,7 +97,7 @@
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
v-if="contentCols.find((col) => col.prop === 'status')?.show"
|
|
v-if="contentCols.find((col) => col.prop === 'status')?.show"
|
|
|
key="status"
|
|
key="status"
|
|
|
- label="状态"
|
|
|
|
|
|
|
+ label="制度状态"
|
|
|
prop="status"
|
|
prop="status"
|
|
|
min-width="100"
|
|
min-width="100"
|
|
|
>
|
|
>
|
|
@@ -79,10 +108,10 @@
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
- v-if="contentCols.find((col) => col.prop === 'created_time')?.show"
|
|
|
|
|
- key="created_time"
|
|
|
|
|
- label="创建时间"
|
|
|
|
|
- prop="created_time"
|
|
|
|
|
|
|
+ v-if="contentCols.find((col) => col.prop === 'updated_time')?.show"
|
|
|
|
|
+ key="updated_time"
|
|
|
|
|
+ label="修改时间"
|
|
|
|
|
+ prop="updated_time"
|
|
|
min-width="160"
|
|
min-width="160"
|
|
|
sortable
|
|
sortable
|
|
|
/>
|
|
/>
|
|
@@ -94,45 +123,28 @@
|
|
|
min-width="240"
|
|
min-width="240"
|
|
|
>
|
|
>
|
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
|
- <el-button
|
|
|
|
|
- v-hasPerm="['module_payment:institution:detail']"
|
|
|
|
|
- type="info"
|
|
|
|
|
- size="small"
|
|
|
|
|
- link
|
|
|
|
|
- icon="View"
|
|
|
|
|
- @click="handleOpenDialog('detail', scope.row.institution_id)"
|
|
|
|
|
- >
|
|
|
|
|
- 详情
|
|
|
|
|
- </el-button>
|
|
|
|
|
<el-button
|
|
<el-button
|
|
|
v-hasPerm="['module_payment:institution:update']"
|
|
v-hasPerm="['module_payment:institution:update']"
|
|
|
- type="primary"
|
|
|
|
|
|
|
+ type="text"
|
|
|
size="small"
|
|
size="small"
|
|
|
- link
|
|
|
|
|
- icon="edit"
|
|
|
|
|
@click="handleOpenDialog('update', scope.row.institution_id)"
|
|
@click="handleOpenDialog('update', scope.row.institution_id)"
|
|
|
>
|
|
>
|
|
|
编辑
|
|
编辑
|
|
|
</el-button>
|
|
</el-button>
|
|
|
<el-button
|
|
<el-button
|
|
|
- v-hasPerm="['module_payment:institution:scope']"
|
|
|
|
|
- type="warning"
|
|
|
|
|
|
|
+ v-hasPerm="['module_payment:institution:manual_pay']"
|
|
|
|
|
+ type="text"
|
|
|
size="small"
|
|
size="small"
|
|
|
- link
|
|
|
|
|
- icon="User"
|
|
|
|
|
- @click="handleOpenScopeDialog(scope.row.institution_id)"
|
|
|
|
|
|
|
+ @click="handleManualPay(scope.row.institution_id)"
|
|
|
>
|
|
>
|
|
|
- 适用范围
|
|
|
|
|
|
|
+ 手动发钱
|
|
|
</el-button>
|
|
</el-button>
|
|
|
<el-button
|
|
<el-button
|
|
|
- v-hasPerm="['module_payment:institution:delete']"
|
|
|
|
|
- type="danger"
|
|
|
|
|
|
|
+ type="text"
|
|
|
size="small"
|
|
size="small"
|
|
|
- link
|
|
|
|
|
- icon="delete"
|
|
|
|
|
- @click="handleDelete(scope.row.institution_id)"
|
|
|
|
|
|
|
+ @click="handleMore(scope.row)"
|
|
|
>
|
|
>
|
|
|
- 删除
|
|
|
|
|
|
|
+ 更多
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
@@ -190,15 +202,13 @@ import InstitutionAPI, {
|
|
|
STATUS_LABEL,
|
|
STATUS_LABEL,
|
|
|
EXPENSE_TYPE_LABEL,
|
|
EXPENSE_TYPE_LABEL,
|
|
|
} from "@/api/module_payment/institution";
|
|
} from "@/api/module_payment/institution";
|
|
|
-import CrudToolbarLeft from "@/components/CURD/CrudToolbarLeft.vue";
|
|
|
|
|
import CrudToolbarRight from "@/components/CURD/CrudToolbarRight.vue";
|
|
import CrudToolbarRight from "@/components/CURD/CrudToolbarRight.vue";
|
|
|
-import PageSearch from "@/components/CURD/PageSearch.vue";
|
|
|
|
|
import PageContent from "@/components/CURD/PageContent.vue";
|
|
import PageContent from "@/components/CURD/PageContent.vue";
|
|
|
import EnhancedDialog from "@/components/CURD/EnhancedDialog.vue";
|
|
import EnhancedDialog from "@/components/CURD/EnhancedDialog.vue";
|
|
|
import InstitutionForm from "./components/InstitutionForm.vue";
|
|
import InstitutionForm from "./components/InstitutionForm.vue";
|
|
|
import InstitutionDetail from "./components/InstitutionDetail.vue";
|
|
import InstitutionDetail from "./components/InstitutionDetail.vue";
|
|
|
import ScopeDialog from "./components/ScopeDialog.vue";
|
|
import ScopeDialog from "./components/ScopeDialog.vue";
|
|
|
-import type { ISearchConfig, IContentConfig } from "@/components/CURD/types";
|
|
|
|
|
|
|
+import type { IContentConfig } from "@/components/CURD/types";
|
|
|
import { useCrudList } from "@/components/CURD/useCrudList";
|
|
import { useCrudList } from "@/components/CURD/useCrudList";
|
|
|
import { useLoadingAction } from "@/composables/useLoadingAction";
|
|
import { useLoadingAction } from "@/composables/useLoadingAction";
|
|
|
import { useRoute } from "vue-router";
|
|
import { useRoute } from "vue-router";
|
|
@@ -207,6 +217,39 @@ import { ref, reactive, computed } from "vue";
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
|
|
|
|
|
|
|
+// 分类标签与对应场景映射
|
|
|
|
|
+const categoryTabs = [
|
|
|
|
|
+ { key: "meal", label: "餐饮", icon: "UtensilsCrossed", scenes: [{ label: "差旅餐饮", value: "business_meal" }, { label: "员工餐补", value: "staff_meal" }, { label: "团建聚餐", value: "team_dinner" }] },
|
|
|
|
|
+ { key: "hotel", label: "酒店", icon: "Building2", scenes: [{ label: "商务出差", value: "business_trip" }, { label: "会议住宿", value: "meeting_hotel" }, { label: "培训住宿", value: "training_hotel" }] },
|
|
|
|
|
+ { key: "flight", label: "机票", icon: "Plane", scenes: [{ label: "国内出差", value: "domestic_flight" }, { label: "国际出差", value: "international_flight" }, { label: "紧急出差", value: "urgent_flight" }] },
|
|
|
|
|
+ { key: "train", label: "火车票", icon: "Train", scenes: [{ label: "省内出差", value: "provincial_train" }, { label: "跨省出差", value: "interprovincial_train" }, { label: "通勤", value: "commute_train" }] },
|
|
|
|
|
+ { key: "bus", label: "公交", icon: "Bus", scenes: [{ label: "市内通勤", value: "city_bus" }, { label: "郊区出行", value: "suburb_bus" }] },
|
|
|
|
|
+ { key: "subway", label: "地铁", icon: "Metro", scenes: [{ label: "日常通勤", value: "daily_subway" }, { label: "加班补贴", value: "overtime_subway" }] },
|
|
|
|
|
+ { key: "car", label: "用车", icon: "Car", scenes: [{ label: "公务用车", value: "official_car" }, { label: "网约车", value: "ride_hailing" }, { label: "自驾补贴", value: "self_drive" }] },
|
|
|
|
|
+ { key: "service", label: "服务", icon: "Headphones", scenes: [{ label: "咨询服务", value: "consult_service" }, { label: "外包服务", value: "outsourcing" }] },
|
|
|
|
|
+ { key: "shopping", label: "商城", icon: "ShoppingCart", scenes: [{ label: "办公用品", value: "office_supplies" }, { label: "劳保用品", value: "labor_protection" }, { label: "员工福利", value: "employee_welfare" }] },
|
|
|
|
|
+ { key: "express", label: "快递", icon: "Truck", scenes: [{ label: "日常快递", value: "daily_express" }, { label: "大件物流", value: "bulk_logistics" }] },
|
|
|
|
|
+ { key: "gas", label: "加油", icon: "Fuel", scenes: [{ label: "公务车加油", value: "official_gas" }, { label: "私家车补贴", value: "private_gas" }] },
|
|
|
|
|
+ { key: "medical", label: "医疗", icon: "Stethoscope", scenes: [{ label: "体检", value: "medical_checkup" }, { label: "门诊报销", value: "outpatient" }, { label: "住院报销", value: "hospitalization" }] },
|
|
|
|
|
+ { key: "default", label: "默认", icon: "FileText", scenes: [{ label: "通用", value: "common" }, { label: "其他", value: "other" }] },
|
|
|
|
|
+ { key: "advertising", label: "电商广告充值", icon: "Monitor", scenes: [{ label: "平台推广", value: "platform_promo" }, { label: "品牌广告", value: "brand_ad" }, { label: "促销活动", value: "promotion" }] },
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+// 当前激活的分类
|
|
|
|
|
+const activeCategory = ref("default");
|
|
|
|
|
+
|
|
|
|
|
+// 当前分类对应的场景列表
|
|
|
|
|
+const currentScenes = computed(() => {
|
|
|
|
|
+ const category = categoryTabs.find(tab => tab.key === activeCategory.value);
|
|
|
|
|
+ return category?.scenes || [{ label: "通用", value: "common" }];
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 场景值
|
|
|
|
|
+const sceneValue = ref("");
|
|
|
|
|
+
|
|
|
|
|
+// 搜索名称
|
|
|
|
|
+const searchName = ref("");
|
|
|
|
|
+
|
|
|
const { searchRef, contentRef, handleQueryClick, handleResetClick, refreshList } =
|
|
const { searchRef, contentRef, handleQueryClick, handleResetClick, refreshList } =
|
|
|
useCrudList();
|
|
useCrudList();
|
|
|
const formRef = ref();
|
|
const formRef = ref();
|
|
@@ -215,22 +258,6 @@ const { pageLoading, loadingText, execute: loadingExecute } = useLoadingAction()
|
|
|
|
|
|
|
|
const enterpriseIdFromUrl = computed(() => route.query.enterprise_id as string | undefined);
|
|
const enterpriseIdFromUrl = computed(() => route.query.enterprise_id as string | undefined);
|
|
|
|
|
|
|
|
-const searchConfig = reactive<ISearchConfig>({
|
|
|
|
|
- permPrefix: "module_payment:institution",
|
|
|
|
|
- colon: true,
|
|
|
|
|
- isExpandable: true,
|
|
|
|
|
- showNumber: 2,
|
|
|
|
|
- form: { labelWidth: "auto" },
|
|
|
|
|
- formItems: [
|
|
|
|
|
- {
|
|
|
|
|
- prop: "enterprise_id",
|
|
|
|
|
- label: "企业ID",
|
|
|
|
|
- type: "input",
|
|
|
|
|
- attrs: { placeholder: "请输入企业ID", clearable: true },
|
|
|
|
|
- },
|
|
|
|
|
- ],
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
const contentCols = reactive<
|
|
const contentCols = reactive<
|
|
|
Array<{
|
|
Array<{
|
|
|
prop?: string;
|
|
prop?: string;
|
|
@@ -240,11 +267,11 @@ const contentCols = reactive<
|
|
|
>([
|
|
>([
|
|
|
{ prop: "selection", label: "选择框", show: false },
|
|
{ prop: "selection", label: "选择框", show: false },
|
|
|
{ prop: "index", label: "序号", show: true },
|
|
{ prop: "index", label: "序号", show: true },
|
|
|
- { prop: "institution_id", label: "制度ID", show: true },
|
|
|
|
|
{ prop: "name", label: "制度名称", show: true },
|
|
{ prop: "name", label: "制度名称", show: true },
|
|
|
|
|
+ { prop: "valid_period", label: "制度有效期", show: true },
|
|
|
{ prop: "expense_type", label: "费用类型", show: true },
|
|
{ prop: "expense_type", label: "费用类型", show: true },
|
|
|
- { prop: "status", label: "状态", show: true },
|
|
|
|
|
- { prop: "created_time", label: "创建时间", show: true },
|
|
|
|
|
|
|
+ { prop: "status", label: "制度状态", show: true },
|
|
|
|
|
+ { prop: "updated_time", label: "修改时间", show: true },
|
|
|
{ prop: "operation", label: "操作", show: true },
|
|
{ prop: "operation", label: "操作", show: true },
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
@@ -332,4 +359,78 @@ async function handleDelete(institutionId?: string) {
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-</script>
|
|
|
|
|
|
|
+
|
|
|
|
|
+function handleCategoryChange(categoryKey: string) {
|
|
|
|
|
+ activeCategory.value = categoryKey;
|
|
|
|
|
+ // 切换分类后,重置场景为当前分类的第一个场景
|
|
|
|
|
+ const category = categoryTabs.find(tab => tab.key === categoryKey);
|
|
|
|
|
+ sceneValue.value = category?.scenes?.[0]?.value || "";
|
|
|
|
|
+ refreshList();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleSearch() {
|
|
|
|
|
+ refreshList();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleManualPay(institutionId?: string) {
|
|
|
|
|
+ if (!institutionId) {
|
|
|
|
|
+ ElMessage.warning("制度ID不存在");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ ElMessage.info(`手动发钱功能:制度ID ${institutionId}`);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function handleMore(row: any) {
|
|
|
|
|
+ ElMessage.info(`更多操作:制度名称 ${row.name}`);
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.category-tabs {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ padding: 16px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.category-tabs__nav {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ padding: 16px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar__scene {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar__label {
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar__right {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.search-bar__input {
|
|
|
|
|
+ width: 200px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.scene-radio-group {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ gap: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|