From a0c1d9021b1a65cc397a2c7a8a9d226c2d9f7539 Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期四, 07 八月 2025 17:17:57 +0800
Subject: [PATCH] feat: 企业

---
 src/views/CPersonManage/CPersonManageList.vue                   |    3 
 src/views/CPersonManage/components/CPersonDetailDialog.vue      |    3 
 .eslintrc-auto-import.json                                      |    4 
 src/views/ProtocolManage/components/AddOrEditTemplateDialog.vue |  124 ++++++
 src/views/ProtocolManage/EditTemplate.vue                       |  196 ++++++++++
 src/views/FinanceManage/components/FinanceDetailDialog.vue      |  101 +++++
 src/hooks/index.ts                                              |    1 
 src/views/OperationManage/OperationManageList.vue               |   12 
 src/views/FinanceManage/FinanceManageList.vue                   |  149 ++++++++
 src/hooks/portraitTable.ts                                      |   50 ++
 src/views/TaskManage/components/SignDetailView.vue              |  100 +++++
 src/views/TaskManage/components/TaskDetailView.vue              |  122 ++++++
 src/views/ProtocolManage/ProtocolManageList.vue                 |  112 ++++++
 src/views/Account/AccountManageList.vue                         |    4 
 auto-imports.d.ts                                               |    7 
 src/views/TaskManage/TaskManageList.vue                         |   38 -
 16 files changed, 982 insertions(+), 44 deletions(-)

diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
index d8574cc..e71035c 100644
--- a/.eslintrc-auto-import.json
+++ b/.eslintrc-auto-import.json
@@ -91,6 +91,8 @@
     "ThemeColorName": true,
     "ThemeColors": true,
     "ThemeColorsType": true,
+    "UsePortraitTableColumnsItem": true,
+    "UsePortraitTableOptions": true,
     "VNode": true,
     "VerifyStatus": true,
     "VerifyStatusColor": true,
@@ -181,6 +183,8 @@
     "useModel": true,
     "useOmit": true,
     "useOmitProps": true,
+    "usePortraitTable": true,
+    "usePortraitTableWithAttachment": true,
     "useResizeHander": true,
     "useRoute": true,
     "useRouteView": true,
diff --git a/auto-imports.d.ts b/auto-imports.d.ts
index 2a77459..7d13730 100644
--- a/auto-imports.d.ts
+++ b/auto-imports.d.ts
@@ -180,6 +180,8 @@
   const useModel: typeof import('vue')['useModel']
   const useOmit: typeof import('./src/hooks/help')['useOmit']
   const useOmitProps: typeof import('./src/hooks/help')['useOmitProps']
+  const usePortraitTable: typeof import('./src/hooks/portraitTable')['usePortraitTable']
+  const usePortraitTableWithAttachment: typeof import('./src/hooks/portraitTable')['usePortraitTableWithAttachment']
   const useResizeHander: typeof import('./src/hooks/useResizeHander')['useResizeHander']
   const useRoute: typeof import('vue-router')['useRoute']
   const useRouteView: typeof import('./src/hooks/useRouteView')['useRouteView']
@@ -233,6 +235,9 @@
   // @ts-ignore
   export type { GlobalEvent, GlobalEventListener, GlobalEventContext } from './src/hooks/useEvent'
   import('./src/hooks/useEvent')
+  // @ts-ignore
+  export type { UsePortraitTableColumnsItem, UsePortraitTableOptions } from './src/hooks/portraitTable'
+  import('./src/hooks/portraitTable')
 }
 
 // for vue template auto import
@@ -398,6 +403,8 @@
     readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
     readonly useOmit: UnwrapRef<typeof import('./src/hooks/help')['useOmit']>
     readonly useOmitProps: UnwrapRef<typeof import('./src/hooks/help')['useOmitProps']>
+    readonly usePortraitTable: UnwrapRef<typeof import('./src/hooks/portraitTable')['usePortraitTable']>
+    readonly usePortraitTableWithAttachment: UnwrapRef<typeof import('./src/hooks/portraitTable')['usePortraitTableWithAttachment']>
     readonly useResizeHander: UnwrapRef<typeof import('./src/hooks/useResizeHander')['useResizeHander']>
     readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
     readonly useRouteView: UnwrapRef<typeof import('./src/hooks/useRouteView')['useRouteView']>
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 32c8db8..b4cd58c 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -8,3 +8,4 @@
 export * from './help';
 export * from './dic';
 export * from './menu';
+export * from './portraitTable';
diff --git a/src/hooks/portraitTable.ts b/src/hooks/portraitTable.ts
new file mode 100644
index 0000000..844586a
--- /dev/null
+++ b/src/hooks/portraitTable.ts
@@ -0,0 +1,50 @@
+import { ColumnsRenderProps } from '@bole-core/components';
+import { MaybeRef } from 'vue';
+
+export type UsePortraitTableColumnsItem<TData extends object = object> = ColumnsRenderProps & {
+  label?: string;
+  key?: keyof TData;
+};
+
+export type UsePortraitTableOptions<TData extends object> = {
+  data: Ref<TData>;
+  columns?: UsePortraitTableColumnsItem<TData>[];
+};
+
+export function usePortraitTable<TData extends object>(options: UsePortraitTableOptions<TData>) {
+  const portraitTableProps = computed(
+    () =>
+      ({
+        data: options.data.value,
+        columns: options.columns ?? [],
+      } as any)
+  );
+
+  return {
+    portraitTableProps,
+  };
+}
+
+type UsePortraitTableWithAttachmentOptions<
+  TData extends object,
+  TAnnexItem extends object = object
+> = UsePortraitTableOptions<TData> & {
+  annexList: Ref<TAnnexItem[]>;
+  columnsRenderProps?: { [key in keyof TAnnexItem]?: ColumnsRenderProps };
+};
+
+export function usePortraitTableWithAttachment<
+  TData extends object,
+  TAnnexItem extends object = object
+>(options: UsePortraitTableWithAttachmentOptions<TData, TAnnexItem>) {
+  const { annexList, columnsRenderProps } = options;
+  const { portraitTableProps } = usePortraitTable(options);
+
+  const portraitTableWithAttachmentProps = computed(() => ({
+    annexList: annexList.value,
+    portraitTableProps: portraitTableProps.value,
+    columnsRenderProps,
+  }));
+
+  return { portraitTableWithAttachmentProps };
+}
diff --git a/src/views/Account/AccountManageList.vue b/src/views/Account/AccountManageList.vue
index a3d529f..c5a3c20 100644
--- a/src/views/Account/AccountManageList.vue
+++ b/src/views/Account/AccountManageList.vue
@@ -44,7 +44,7 @@
 } from '@bole-core/components';
 import { useAccess } from '@/hooks';
 import { RoleClientType } from '@/constants';
-import { Message, OrderInputType } from '@bole-core/core';
+import { Message } from '@bole-core/core';
 import AddOrEditAccountDialog from './components/AddOrEditAccountDialog.vue';
 
 defineOptions({
@@ -96,7 +96,7 @@
   },
   {
     defaultExtraParams: {
-      orderInput: [{ property: 'id', order: OrderInputType.Desc }],
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
       keyword: '',
     },
     columnsRenderProps: {
diff --git a/src/views/CPersonManage/CPersonManageList.vue b/src/views/CPersonManage/CPersonManageList.vue
index afbed41..ac1cda8 100644
--- a/src/views/CPersonManage/CPersonManageList.vue
+++ b/src/views/CPersonManage/CPersonManageList.vue
@@ -80,7 +80,6 @@
 import { useAccess, useGlobalEventContext } from '@/hooks';
 import { Gender } from '@/constants';
 import CPersonDetailDialog from './components/CPersonDetailDialog.vue';
-import { OrderInputType } from '@bole-core/core';
 import { convertApi2FormUrlOnlyOne, format } from '@/utils';
 import { ModelValueType } from 'element-plus';
 
@@ -168,7 +167,7 @@
       realVerifyStatus: '' as any as boolean,
       nearlyHireDateTime: [] as unknown as ModelValueType,
       nearlySignDateTime: [] as unknown as ModelValueType,
-      orderInput: [{ property: 'userId', order: OrderInputType.Desc }],
+      orderInput: [{ property: 'userId', order: EnumPagedListOrder.Desc }],
     },
     queryKey: ['flexEnterpriseWokerServices/getUserClientList'],
     columnsRenderProps: {
diff --git a/src/views/CPersonManage/components/CPersonDetailDialog.vue b/src/views/CPersonManage/components/CPersonDetailDialog.vue
index e1e3b09..ddc2e74 100644
--- a/src/views/CPersonManage/components/CPersonDetailDialog.vue
+++ b/src/views/CPersonManage/components/CPersonDetailDialog.vue
@@ -58,7 +58,6 @@
   ProFormInputNumber,
   defineColumns,
 } from '@bole-core/components';
-import { OrderInputType } from '@bole-core/core';
 import _ from 'lodash';
 import { setOSSLink } from '@/utils';
 import {
@@ -165,7 +164,7 @@
   },
   {
     defaultExtraParams: {
-      orderInput: [{ property: 'applyTime', order: OrderInputType.Desc }],
+      orderInput: [{ property: 'applyTime', order: EnumPagedListOrder.Desc }],
     },
     columnsRenderProps: {
       applyTime: { type: 'date' },
diff --git a/src/views/FinanceManage/FinanceManageList.vue b/src/views/FinanceManage/FinanceManageList.vue
new file mode 100644
index 0000000..fc1c742
--- /dev/null
+++ b/src/views/FinanceManage/FinanceManageList.vue
@@ -0,0 +1,149 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem tip-content="鍙戝竷鐘舵��">
+            <FieldRadio
+              v-model="extraParamState.status"
+              :value-enum="[
+                { value: true, label: '鍙戝竷涓�' },
+                { value: false, label: '宸插仠姝�' },
+              ]"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鎺ㄨ崘鐘舵��">
+            <FieldRadio
+              v-model="extraParamState.status"
+              :value-enum="[
+                { value: true, label: '宸叉帹鑽�' },
+                { value: false, label: '鏈帹鑽�' },
+              ]"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鍙戝竷鏃堕棿">
+            <FieldDatePicker
+              v-model="extraParamState.beginDate"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 260px"
+              placeholder="浠诲姟鍚嶇О"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+    <FinanceDetailDialog v-bind="dialogProps" />
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  OperationBtnType,
+  ProTableV2,
+  SearchInput,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  FieldDatePicker,
+  FieldRadio,
+  useFormDialog,
+} from '@bole-core/components';
+import { useAccess } from '@/hooks';
+import { ModelValueType } from 'element-plus';
+import * as enterpriseServices from '@/services/api/enterprise';
+import FinanceDetailDialog from './components/FinanceDetailDialog.vue';
+
+defineOptions({
+  name: 'FinanceManageList',
+});
+
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: { emits: { onClick: (role) => openDialog(role) } },
+};
+
+const { column, operationBtns } = useAccess({
+  operationBtnMap,
+});
+
+const router = useRouter();
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetEnterprisesQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        // searchKeys: extraParamState.keyword,
+      };
+      let res = await enterpriseServices.getEnterprises(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      pageType: '' as any as number,
+      status: '' as any as boolean,
+      beginDate: [] as unknown as ModelValueType,
+      endDate: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Asc }],
+    },
+    columnsRenderProps: {},
+  }
+);
+
+const { dialogProps, handleEdit, editForm } = useFormDialog({
+  defaultFormParams: {
+    id: '',
+  },
+});
+
+function openDialog(row) {
+  handleEdit({
+    id: row.id,
+  });
+}
+</script>
diff --git a/src/views/FinanceManage/components/FinanceDetailDialog.vue b/src/views/FinanceManage/components/FinanceDetailDialog.vue
new file mode 100644
index 0000000..899ce02
--- /dev/null
+++ b/src/views/FinanceManage/components/FinanceDetailDialog.vue
@@ -0,0 +1,101 @@
+<template>
+  <ProDialog title="鏄庣粏" v-model="visible" destroy-on-close draggable>
+    <PortraitTable v-bind="portraitTableProps" label-width="140px" :col-number="2"></PortraitTable>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')" type="primary">纭畾</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { ProDialog, toThousand } from '@bole-core/components';
+import { usePortraitTable } from '@/hooks';
+
+defineOptions({
+  name: 'FinanceDetailDialog',
+});
+
+type Form = {
+  name?: string;
+};
+
+const visible = defineModel({ type: Boolean });
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'onCancel'): void;
+}>();
+
+const { portraitTableProps } = usePortraitTable({
+  data: form,
+  columns: [
+    {
+      label: '浠樻浜鸿处鎴�',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '鏀舵浜鸿处鎴�',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '浠樻浜哄悕绉�',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '鏀舵浜哄悕绉�',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '浠樻浜哄紑鎴疯',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '鏀舵浜哄紑鎴疯',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '甯佺',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '浜ゆ槗閲戦',
+      key: 'name',
+      type: 'money',
+    },
+    {
+      label: '鐢ㄩ��',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '鎽樿',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '浜ゆ槗鏃堕棿',
+      key: 'name',
+      type: 'text',
+    },
+    {
+      label: '浜ゆ槗鐘舵��',
+      key: 'name',
+      type: 'text',
+    },
+  ],
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/OperationManage/OperationManageList.vue b/src/views/OperationManage/OperationManageList.vue
index d4e16c3..026deb5 100644
--- a/src/views/OperationManage/OperationManageList.vue
+++ b/src/views/OperationManage/OperationManageList.vue
@@ -7,7 +7,7 @@
             <FieldSelect
               v-model="extraParamState.pageType"
               placeholder="骞垮憡椤甸潰"
-              :value-enum="FlexWorkerEleSignEnumText"
+              :value-enum="[]"
               clearable
               @change="getAdvertiseOnShowList()"
             />
@@ -15,7 +15,10 @@
           <QueryFilterItem tip-content="鐘舵��">
             <FieldRadio
               v-model="extraParamState.status"
-              :value-enum="FlexWorkerEleSignEnumText"
+              :value-enum="[
+                { value: true, label: '灞曠ず涓�' },
+                { value: false, label: '宸蹭笅鏋�' },
+              ]"
               buttonStyle
               showAllBtn
               @change="getAdvertiseOnShowList()"
@@ -89,7 +92,7 @@
 import { FlexWorkerEleSignEnumText } from '@/constants';
 import { ModelValueType } from 'element-plus';
 import { format, setOSSLink, convertApi2FormUrl, convertFormUrl2Api } from '@/utils';
-import { OrderInputType, Message } from '@bole-core/core';
+import { Message } from '@bole-core/core';
 
 defineOptions({
   name: 'OperationManageList',
@@ -158,10 +161,9 @@
       status: '' as any as boolean,
       beginDate: [] as unknown as ModelValueType,
       endDate: [] as unknown as ModelValueType,
-      orderInput: [{ property: 'sort', order: OrderInputType.Asc }],
+      orderInput: [{ property: 'sort', order: EnumPagedListOrder.Asc }],
     },
     columnsRenderProps: {},
-    columnPropsMap: ['advertiseBeginDate', 'advertiseEndDate'],
   }
 );
 
diff --git a/src/views/ProtocolManage/EditTemplate.vue b/src/views/ProtocolManage/EditTemplate.vue
new file mode 100644
index 0000000..1faf700
--- /dev/null
+++ b/src/views/ProtocolManage/EditTemplate.vue
@@ -0,0 +1,196 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem>
+            <FieldRadio
+              v-model="extraParamState.status"
+              :value-enum="[
+                { value: 1, label: '寰呭埗鐗�' },
+                { value: 2, label: '宸插畬鎴�' },
+              ]"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="瀹㈡埛涓婁紶鏃堕棿">
+            <FieldDatePicker
+              v-model="extraParamState.beginDate"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鍒剁増鏃堕棿">
+            <FieldDatePicker
+              v-model="extraParamState.beginDate"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 260px"
+              placeholder="妯℃澘鍚嶇О/ID/涓氬姟缂栫爜"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+        <template #btn>
+          <el-button @click="openDialog()" icon="Plus" type="primary">鏂板妯℃澘</el-button>
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+    <AddOrEditTemplateDialog v-bind="dialogProps" />
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  OperationBtnType,
+  ProTableV2,
+  SearchInput,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  FieldDatePicker,
+  FieldRadio,
+  useFormDialog,
+  UploadUserFile,
+} from '@bole-core/components';
+import { useAccess } from '@/hooks';
+import { ModelValueType } from 'element-plus';
+import * as enterpriseServices from '@/services/api/enterprise';
+import AddOrEditTemplateDialog from './components/AddOrEditTemplateDialog.vue';
+import { Message } from '@bole-core/core';
+
+defineOptions({
+  name: 'EditTemplate',
+});
+
+const operationBtnMap: Record<string, OperationBtnType> = {
+  editBtn: { emits: { onClick: (role) => openDialog(role) } },
+  editTemplateBtn: {
+    emits: { onClick: (role) => openDialog(role) },
+    extraProps: {
+      hide: (row) => false,
+    },
+  },
+  downloadBtn: {
+    emits: { onClick: (role) => handleDownload(role) },
+  },
+  delBtn: {
+    emits: { onClick: (role) => handleDelete(role) },
+    extraProps: {
+      hide: (row) => false,
+    },
+  },
+
+  logBtn: {
+    emits: { onClick: (role) => openLogDialog(role) },
+  },
+};
+
+const { column, operationBtns } = useAccess({
+  operationBtnMap,
+});
+
+const router = useRouter();
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetEnterprisesQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        // searchKeys: extraParamState.keyword,
+      };
+      let res = await enterpriseServices.getEnterprises(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      status: '' as any as boolean,
+      beginDate: [] as unknown as ModelValueType,
+      endDate: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Asc }],
+    },
+    columnsRenderProps: {},
+  }
+);
+
+const { dialogProps, handleEdit, handleAdd, editForm } = useFormDialog({
+  onConfirm: handleAddOrEdit,
+  defaultFormParams: {
+    id: '',
+    templateId: '',
+    name: '',
+    bussinessCode: '',
+    templateFileUrl: [] as UploadUserFile[],
+    title: '鏂板妯℃澘',
+  },
+});
+
+function openDialog(row?) {
+  if (row) {
+    handleEdit({
+      id: '',
+      name: '',
+      bussinessCode: '',
+      templateId: '',
+      templateFileUrl: [] as UploadUserFile[],
+    });
+  } else {
+    handleAdd();
+  }
+}
+
+async function handleAddOrEdit() {}
+
+function handleDownload(row) {}
+async function handleDelete(row) {
+  try {
+    await Message.deleteMessage();
+  } catch (error) {}
+}
+
+function openLogDialog(row) {}
+</script>
diff --git a/src/views/ProtocolManage/ProtocolManageList.vue b/src/views/ProtocolManage/ProtocolManageList.vue
new file mode 100644
index 0000000..aa1c6e0
--- /dev/null
+++ b/src/views/ProtocolManage/ProtocolManageList.vue
@@ -0,0 +1,112 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem>
+            <FieldRadio
+              v-model="extraParamState.status"
+              :value-enum="[{ value: 1, label: '寰呭埗鐗�' }]"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 260px"
+              placeholder="浼佷笟/鐢叉柟浼佷笟"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  OperationBtnType,
+  ProTableV2,
+  SearchInput,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  FieldRadio,
+} from '@bole-core/components';
+import { useAccess } from '@/hooks';
+import * as enterpriseServices from '@/services/api/enterprise';
+
+defineOptions({
+  name: 'ProtocolManageList',
+});
+
+const operationBtnMap: Record<string, OperationBtnType> = {
+  editTemplateBtn: { emits: { onClick: (role) => goEdit(role) } },
+};
+
+const { column, operationBtns } = useAccess({
+  operationBtnMap,
+});
+
+const router = useRouter();
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetEnterprisesQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        // searchKeys: extraParamState.keyword,
+      };
+      let res = await enterpriseServices.getEnterprises(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      status: '',
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Asc }],
+    },
+    columnsRenderProps: {},
+  }
+);
+
+function goEdit(row) {
+  router.push({
+    name: 'EditTemplate',
+    params: {
+      id: row.id,
+    },
+  });
+}
+</script>
diff --git a/src/views/ProtocolManage/components/AddOrEditTemplateDialog.vue b/src/views/ProtocolManage/components/AddOrEditTemplateDialog.vue
new file mode 100644
index 0000000..2bc2f6d
--- /dev/null
+++ b/src/views/ProtocolManage/components/AddOrEditTemplateDialog.vue
@@ -0,0 +1,124 @@
+<template>
+  <ProDialog
+    :title="form.title"
+    v-model="visible"
+    destroy-on-close
+    draggable
+    @close="onDialogClose"
+  >
+    <ProForm :model="form" ref="dialogForm" label-width="120px">
+      <ProFormItemV2
+        label="妯℃澘ID锛�"
+        prop="templateId"
+        :check-rules="[{ message: '璇疯緭鍏ユā鏉縄D' }]"
+      >
+        <ProFormText
+          placeholder="璇疯緭鍏ユā鏉縄D"
+          v-model.trim="form.templateId"
+          :formatter="filterCN"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="閫氶亾锛�"
+        prop="templateId"
+        :check-rules="[{ message: '璇烽�夋嫨鐢靛瓙绛鹃�氶亾' }]"
+      >
+        <ProFormSelect
+          placeholder="璇烽�夋嫨鐢靛瓙绛鹃�氶亾"
+          v-model="form.templateId"
+          :value-enum="[{ label: 1, value: '鏀粯瀹�' }]"
+        ></ProFormSelect>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="涓氬姟缂栫爜锛�"
+        prop="bussinessCode"
+        :check-rules="[{ message: '璇疯緭鍏ヤ笟鍔$紪鐮�' }]"
+      >
+        <ProFormText
+          placeholder="璇疯緭鍏ヤ笟鍔$紪鐮�"
+          v-model.trim="form.bussinessCode"
+          :maxlength="5"
+          :formatter="filterNumbersFromString"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2 label="妯℃澘鍚嶇О锛�" prop="name" :check-rules="[{ message: '璇疯緭鍏ユā鏉垮悕绉�' }]">
+        <ProFormText
+          placeholder="璇疯緭鍏ユā鏉垮悕绉�"
+          v-model.trim="form.name"
+          :maxlength="15"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="涓婁紶妯℃澘锛�"
+        prop="templateFileUrl"
+        :check-rules="[{ message: '璇蜂笂浼犳ā鏉�', type: 'upload' }]"
+      >
+        <ProFormUpload
+          v-model:file-url="form.templateFileUrl"
+          :limit="1"
+          :limitFileSize="10"
+          accept="pdf"
+        ></ProFormUpload>
+      </ProFormItemV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  ProDialog,
+  UploadUserFile,
+  ProForm,
+  ProFormItemV2,
+  ProFormText,
+  ProFormUpload,
+  ProFormSelect,
+} from '@bole-core/components';
+import { filterCN, filterNumbersFromString } from '@/utils';
+import { FormInstance } from 'element-plus';
+
+defineOptions({
+  name: 'AddOrEditTemplateDialog',
+});
+
+const visible = defineModel({ type: Boolean });
+
+type Form = {
+  title?: string;
+  id: string;
+  templateId: string;
+  name: string;
+  bussinessCode: string;
+  templateFileUrl: UploadUserFile[];
+};
+
+const form = defineModel<Form>('form');
+
+const emit = defineEmits<{
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+function onDialogClose() {
+  if (!dialogForm.value) return;
+  dialogForm.value.resetFields();
+}
+
+function handleConfirm() {
+  if (!dialogForm.value) return;
+  dialogForm.value.validate((valid) => {
+    if (valid) {
+      emit('onConfirm');
+    } else {
+      return;
+    }
+  });
+}
+</script>
diff --git a/src/views/TaskManage/TaskManageList.vue b/src/views/TaskManage/TaskManageList.vue
index 3be9206..1409251 100644
--- a/src/views/TaskManage/TaskManageList.vue
+++ b/src/views/TaskManage/TaskManageList.vue
@@ -3,19 +3,13 @@
     <AppContainer>
       <ProTableQueryFilterBar @on-reset="reset">
         <template #query>
-          <QueryFilterItem>
-            <FieldSelect
-              v-model="extraParamState.pageType"
-              placeholder="骞垮憡椤甸潰"
-              :value-enum="FlexWorkerEleSignEnumText"
-              clearable
-              @change="getList()"
-            />
-          </QueryFilterItem>
           <QueryFilterItem tip-content="鍙戝竷鐘舵��">
             <FieldRadio
               v-model="extraParamState.status"
-              :value-enum="FlexWorkerEleSignEnumText"
+              :value-enum="[
+                { value: true, label: '鍙戝竷涓�' },
+                { value: false, label: '宸插仠姝�' },
+              ]"
               buttonStyle
               showAllBtn
               @change="getList()"
@@ -24,7 +18,10 @@
           <QueryFilterItem tip-content="鎺ㄨ崘鐘舵��">
             <FieldRadio
               v-model="extraParamState.status"
-              :value-enum="FlexWorkerEleSignEnumText"
+              :value-enum="[
+                { value: true, label: '宸叉帹鑽�' },
+                { value: false, label: '鏈帹鑽�' },
+              ]"
               buttonStyle
               showAllBtn
               @change="getList()"
@@ -69,13 +66,11 @@
   QueryFilterItem,
   useTable,
   FieldDatePicker,
-  FieldSelect,
   FieldRadio,
 } from '@bole-core/components';
 import { useAccess } from '@/hooks';
-import { FlexWorkerEleSignEnumText } from '@/constants';
 import { ModelValueType } from 'element-plus';
-import { OrderInputType } from '@bole-core/core';
+import * as enterpriseServices from '@/services/api/enterprise';
 
 defineOptions({
   name: 'OperationManageList',
@@ -83,13 +78,13 @@
 
 const operationBtnMap: Record<string, OperationBtnType> = {
   detailBtn: { emits: { onClick: (role) => goDetail(role) } },
-  takeOnBtn: {
+  recommendBtn: {
     emits: { onClick: (role) => setAdvertiseOnShowStatus(role) },
     extraProps: {
       hide: (row) => row.status,
     },
   },
-  takeDownBtn: {
+  cancelRecommendBtn: {
     emits: { onClick: (role) => setAdvertiseOnShowStatus(role) },
     props: { type: 'danger' },
     extraProps: {
@@ -123,15 +118,15 @@
 } = useTable(
   async ({ pageIndex, pageSize }, extraParamState) => {
     try {
-      let params: API.GetUserClientForBackInput = {
+      let params: API.GetEnterprisesQuery = {
         pageModel: {
           rows: pageSize,
           page: pageIndex,
           orderInput: extraParamState.orderInput,
         },
-        searchKeys: extraParamState.keyword,
+        // searchKeys: extraParamState.keyword,
       };
-      let res = await flexEnterpriseWokerServices.getUserClientList(params, {
+      let res = await enterpriseServices.getEnterprises(params, {
         showLoading: !state.loading,
       });
       return res;
@@ -144,10 +139,9 @@
       status: '' as any as boolean,
       beginDate: [] as unknown as ModelValueType,
       endDate: [] as unknown as ModelValueType,
-      orderInput: [{ property: 'sort', order: OrderInputType.Asc }],
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Asc }],
     },
     columnsRenderProps: {},
-    columnPropsMap: ['advertiseBeginDate', 'advertiseEndDate'],
   }
 );
 
@@ -157,6 +151,6 @@
 }
 
 function goDetail(row) {
-  router.push({ name: 'TaskDetail', params: { id: row?.id ?? '' } });
+  router.push({ name: 'TaskManageDetail', params: { id: row?.id ?? '' } });
 }
 </script>
diff --git a/src/views/TaskManage/components/SignDetailView.vue b/src/views/TaskManage/components/SignDetailView.vue
index ccbb659..8a59d91 100644
--- a/src/views/TaskManage/components/SignDetailView.vue
+++ b/src/views/TaskManage/components/SignDetailView.vue
@@ -1,13 +1,103 @@
 <template>
-  <div>SignDetailView</div>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
 </template>
 
 <script setup lang="ts">
+import {
+  OperationBtnType,
+  ProTableV2,
+  LoadingLayout,
+  AppContainer,
+  useTable,
+} from '@bole-core/components';
+import { useAccess } from '@/hooks';
+import { ModelValueType } from 'element-plus';
+import * as enterpriseServices from '@/services/api/enterprise';
+
 defineOptions({
   name: 'SignDetailView',
 });
-</script>
 
-<style lang="scss" scoped>
-@use '@/style/common.scss' as *;
-</style>
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: { emits: { onClick: (role) => goDetail(role) } },
+  recommendBtn: {
+    emits: { onClick: (role) => setAdvertiseOnShowStatus(role) },
+    extraProps: {
+      hide: (row) => row.status,
+    },
+  },
+  cancelRecommendBtn: {
+    emits: { onClick: (role) => setAdvertiseOnShowStatus(role) },
+    props: { type: 'danger' },
+    extraProps: {
+      hide: (row) => !row.status,
+    },
+  },
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
+
+const router = useRouter();
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetEnterprisesQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        // searchKeys: extraParamState.keyword,
+      };
+      let res = await enterpriseServices.getEnterprises(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      pageType: '' as any as number,
+      status: '' as any as boolean,
+      beginDate: [] as unknown as ModelValueType,
+      endDate: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Asc }],
+    },
+    columnsRenderProps: {},
+  }
+);
+
+async function setAdvertiseOnShowStatus(row) {
+  try {
+  } catch (error) {}
+}
+
+function goDetail(row) {
+  router.push({ name: 'TaskManageDetail', params: { id: row?.id ?? '' } });
+}
+</script>
diff --git a/src/views/TaskManage/components/TaskDetailView.vue b/src/views/TaskManage/components/TaskDetailView.vue
index 8d86b79..668e441 100644
--- a/src/views/TaskManage/components/TaskDetailView.vue
+++ b/src/views/TaskManage/components/TaskDetailView.vue
@@ -6,16 +6,107 @@
           <ProFormCol>
             <ProFormColItem :span="12">
               <ProFormItemV2 label="浠诲姟鍚嶇О:" prop="name">
-                <ProFormText v-model.trim="detail.name" />
+                <ProFormText v-model.trim="detail.enterpriseName" />
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormItemV2 label="鏈嶅姟璐�:" prop="salaryType">
+              <RadioWithExtra
+                v-model="detail.enterpriseName"
+                :value-enum="[
+                  { value: 1, text: '鎸夋湀' },
+                  { value: 2, text: '鎸夋棩' },
+                ]"
+                enumLabelKey="text"
+                enum-value-key="value"
+                :showExtra="true"
+              >
+                <template #extra>
+                  <ProFormInputNumber
+                    :controls="false"
+                    v-model="detail.enterpriseName"
+                    :unit="detail.enterpriseName === '' ? '鍏�/鏈�' : '鍏�/鏃�'"
+                  ></ProFormInputNumber>
+                </template>
+              </RadioWithExtra>
+            </ProFormItemV2>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="缁撶畻鏂瑰紡:" prop="salaryType">
+                <ProFormRadio
+                  v-model="detail.enterpriseName"
+                  :value-enum="[
+                    { label: '鏈堢粨', value: 1 },
+                    { label: '鏃ョ粨', value: 2 },
+                  ]"
+                />
               </ProFormItemV2>
             </ProFormColItem>
           </ProFormCol>
           <ProFormCol>
             <ProFormColItem :span="12">
-              <ProFormItemV2 label="浠诲姟鍚嶇О:" prop="name"> </ProFormItemV2>
+              <ProFormItemV2 label="绂忓埄:" prop="salaryType">
+                <ProFormRadio v-model="detail.enterpriseName" :value-enum="dictionaryDataList" />
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="骞撮緞鑼冨洿:" prop="ageRange">
+                <ProFormInputNumber v-model="detail.enterpriseName"></ProFormInputNumber>
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="鎬у埆闇�姹�:" prop="salaryType">
+                <ProFormRadio
+                  v-model="detail.enterpriseName"
+                  :value-enum="[
+                    { label: '鐢�', value: 1 },
+                    { label: '濂�', value: 2 },
+                  ]"
+                />
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="璧勬牸璇佷功:" prop="salaryType">
+                <ProFormRadio v-model="detail.enterpriseName" :value-enum="dictionaryDataList" />
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="浠诲姟鍦扮偣:" prop="areaList">
+                <!-- <ProFromAddressSelectV2
+                  v-model:areaList="detail.areaList"
+                  areaListPlaceholder="璇烽�夋嫨"
+                  :layer="AreaType.Area"
+                /> -->
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="浠诲姟鏃堕棿:" prop="creationTime" mode="read">
+                <ProFormDatePicker
+                  v-model="detail.enterpriseName"
+                  type="daterange"
+                  range-separator="鑷�"
+                  start-placeholder="寮�濮嬫棩鏈�"
+                  end-placeholder="缁撴潫鏃ユ湡"
+                ></ProFormDatePicker>
+              </ProFormItemV2>
             </ProFormColItem>
           </ProFormCol>
         </ProForm>
+        <template #footer>
+          <el-button @click="handleBack">鍏抽棴</el-button>
+        </template>
       </PageFormLayout>
     </AppContainer>
   </LoadingLayout>
@@ -32,8 +123,12 @@
   ProFormItemV2,
   ProFormText,
   ProFormInputNumber,
+  ProFormRadio,
+  ProFormDatePicker,
 } from '@bole-core/components';
 import { useQuery } from '@tanstack/vue-query';
+import { AreaType } from '@/constants';
+import * as enterpriseServices from '@/services/api/enterprise';
 
 defineOptions({
   name: 'TaskDetailView',
@@ -41,15 +136,30 @@
 
 const route = useRoute();
 const id = route.params?.id as string;
+const { closeViewPush } = useRouteView();
+const { dictionaryDataList } = useDictionaryDataSelect({
+  categoryCode: computed(() => CategoryCode.Welfare),
+});
 
 const { data: detail, isLoading } = useQuery({
-  queryKey: ['customerServices/getParkCustomerManageBaseDetail', id],
+  queryKey: ['enterpriseServices/getEnterprise', id],
   queryFn: async () => {
-    return await customerServices.getParkCustomerManageBaseDetail({ id: id });
+    return await enterpriseServices.getEnterprise(
+      { id: id },
+      {
+        showLoading: false,
+      }
+    );
   },
-  placeholderData: () => ({} as API.GetUserClientForBackOutput),
-  enabled: !!id,
+  placeholderData: () => ({} as API.GetEnterpriseQueryResult),
+  enabled: computed(() => !!id),
 });
+
+function handleBack() {
+  closeViewPush(route, {
+    name: 'TaskManageList',
+  });
+}
 </script>
 
 <style lang="scss" scoped>

--
Gitblit v1.9.1