Browse Source

feat: 开票内容相关功能

outaozhen 3 năm trước cách đây
mục cha
commit
98af4008fc

+ 6 - 0
config/routes.ts

@@ -86,6 +86,12 @@
         name: 'contact',
         component: './business/Contact',
         access: 'authRouteFilter'
+      },
+      {
+        path: '/business/invoice',
+        name: 'invoice',
+        component: './business/Invoice',
+        access: 'authRouteFilter'
       }
       // {
       //   path: '/business/notice',

+ 1 - 0
src/locales/zh-CN/menu.ts

@@ -14,6 +14,7 @@ export default {
   'menu.business': '业务参数',
   'menu.business.attendance': '考勤',
   'menu.business.contact': '客户',
+  'menu.business.invoice': '开票合同',
   'menu.business.notice': '通知中心',
   'menu.login': '登录',
   'menu.register': '注册',

+ 231 - 0
src/pages/Business/Invoice/index.tsx

@@ -0,0 +1,231 @@
+import React, { useState, useRef } from 'react'
+import { Button, Popconfirm, Table, message } from 'antd'
+import { ModalForm, ProFormText, ProFormSelect } from '@ant-design/pro-form'
+import ShowTitleMenu from '../Attendance/components/ShowTitleMenu'
+import type { ColumnsType } from 'antd/lib/table'
+import { MenuOutlined } from '@ant-design/icons'
+import { Delete } from '@icon-park/react'
+import { SortableHandle } from 'react-sortable-hoc'
+import {
+  fetchInvoiceList,
+  addInvoiceItem,
+  updateInvoiceItem,
+  deleteInvoiceItem
+} from '@/services/user/system'
+import { useRequest } from 'umi'
+
+const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />)
+// const SortableItem = SortableElement(props => <tr {...props} />)
+// const SortableBody = SortableContainer(props => <tbody {...props} />)
+const isEnableEnum = {
+  open: '启用',
+  close: '停用'
+}
+enum modalType {
+  CREATE = 0,
+  UPDATE = 1
+}
+const modalTitleType = {
+  1: '开票内容'
+}
+
+const Invoice: React.FC = () => {
+  const formRef = useRef<FormInstance>(null)
+  const [state, setState] = useState({
+    id: '',
+    menuId: 1,
+    dataSource: [],
+    visible: false,
+    enable: 'open',
+    type: modalType.CREATE
+  })
+  const onSelect = (menuId: string) => {
+    setState({ ...state, menuId })
+  }
+  const { run: tryGetInvoiceList } = useRequest(fetchInvoiceList, {
+    onSuccess: (result: API.InvoicegroupItem[]) => {
+      setState({ ...state, dataSource: result })
+    }
+  })
+  const { run: tryAddInvoiceItem } = useRequest(addInvoiceItem, {
+    manual: true,
+    onSuccess: async () => {
+      tryGetInvoiceList()
+      formRef.current?.resetFields()
+      message.success('添加成功')
+    },
+    onError: e => {
+      message.error(e.message)
+    }
+  })
+  const { run: tryUpdateInvoiceItem } = useRequest(updateInvoiceItem, {
+    manual: true,
+    onSuccess: async () => {
+      tryGetInvoiceList()
+      formRef.current?.resetFields()
+      message.success('编辑成功')
+    },
+    onError: e => {
+      message.error(e.message)
+    }
+  })
+  const { run: tryDeleteInvoiceItem } = useRequest(deleteInvoiceItem, {
+    manual: true,
+    onSuccess: async () => {
+      await tryGetInvoiceList()
+    },
+    onError: e => {
+      message.error(e.message)
+    }
+  })
+  const mainColumns: ColumnsType<API.InvoicegroupItem> = [
+    {
+      dataIndex: 'sort',
+      title: '排序',
+      render: () => <DragHandle />
+    },
+    {
+      dataIndex: 'name',
+      title: '开票内容'
+    },
+    {
+      dataIndex: 'enable',
+      title: '状态',
+      render: enable => (
+        <span>
+          {enable === 'close' ? (
+            <span className="text-red-500 cursor-pointer hover:text-red-600">
+              {isEnableEnum[enable]}
+            </span>
+          ) : (
+            <span>{isEnableEnum[enable]}</span>
+          )}
+        </span>
+      )
+    },
+    {
+      dataIndex: 'opreate',
+      title: '操作',
+      render: (_, record) => (
+        <div className="divide-x divide-bg-gray-400 flex flex-row">
+          <div
+            className="pr-2 text-primary cursor-pointer hover:text-hex-967bbd"
+            onClick={() => {
+              formRef.current?.setFieldsValue({ ...record })
+              setState({ ...state, visible: true, type: modalType.UPDATE })
+            }}
+          >
+            编辑
+          </div>
+          {record.enable === 'open' ? (
+            <Popconfirm
+              title="是否停用此开票内容"
+              onConfirm={() =>
+                tryUpdateInvoiceItem({ id: record.id, name: record.name, enable: 'open' })
+              }
+            >
+              <div className="px-2 text-red-500 cursor-pointer hover:text-red-600">停用</div>
+            </Popconfirm>
+          ) : null}
+          {record.enable === 'close' && (
+            <div
+              className="px-2 text-primary cursor-pointer hover:text-hex-967bbd"
+              onConfirm={() =>
+                tryUpdateInvoiceItem({ id: record.id, name: record.name, enable: 'close' })
+              }
+            >
+              启用
+            </div>
+          )}
+          <Popconfirm title="确认删除?" onConfirm={() => tryDeleteInvoiceItem(record.id)}>
+            <div className="pl-2 text-hex-fd3995 cursor-pointer hover:text-hex-e7026e">
+              <Delete />
+            </div>
+          </Popconfirm>
+        </div>
+      )
+    }
+  ]
+
+  return (
+    <div className="h-full w-full flex flex-row">
+      <ShowTitleMenu
+        onSelect={onSelect}
+        options={[{ label: '开票内容', value: 1 }]}
+        defaultValue={1}
+      />
+      <div className="w-max-3/4">
+        <div className="ml-8 bg-white p-4 shadow-md shadow-hex-3e2c5a relative">
+          {state.menuId === 1 ? (
+            <>
+              <div className="pb-3 border-b border-b-black border-opacity-8 mb-3 flex items-center justify-between">
+                <div>开票内容</div>
+                <Button
+                  type="primary"
+                  onClick={() => setState({ ...state, visible: true, type: modalType.CREATE })}
+                >
+                  添加新内容
+                </Button>
+              </div>
+              <Table
+                columns={mainColumns}
+                dataSource={state.dataSource}
+                bordered
+                rowKey={row => row.id}
+              />
+            </>
+          ) : null}
+        </div>
+      </div>
+      <ModalForm
+        visible={state.visible}
+        formRef={formRef}
+        onVisibleChange={show => setState({ ...state, visible: show })}
+        title={`${state.type === modalType.CREATE ? '新增' : '编辑'}${
+          modalTitleType[state.menuId]
+        }`}
+        onFinish={async value => {
+          try {
+            if (state.type === modalType.CREATE && state.menuId === 1) {
+              await tryAddInvoiceItem({
+                ...value
+              })
+            }
+            if (state.type === modalType.UPDATE && state.menuId === 1) {
+              await tryUpdateInvoiceItem({
+                ...value
+              })
+            }
+            return true
+          } catch (error) {
+            message.error(`${state.type === modalType.CREATE ? '创建' : '更新'}失败,请重试`)
+            return false
+          }
+        }}
+      >
+        {state.menuId === 1 ? (
+          <>
+            <ProFormText name="id" hidden />
+            <ProFormText name="name" label="开票内容" required />
+            <ProFormSelect
+              options={[
+                {
+                  value: '6',
+                  label: '6'
+                },
+                {
+                  value: '13',
+                  label: '13'
+                }
+              ]}
+              name="rate"
+              label="税率"
+            />
+          </>
+        ) : null}
+      </ModalForm>
+    </div>
+  )
+}
+
+export default Invoice

+ 29 - 0
src/services/user/system.ts

@@ -56,3 +56,32 @@ export async function updateParameters(params: API.UpdateParameters) {
     data: params
   })
 }
+
+/** 获取发票内容列表 */
+export async function fetchInvoiceList() {
+  return request<API.InvoiceList[]>('/invoice/item/list')
+}
+
+/** 新增发票内容 */
+export async function addInvoiceItem(params: API.AddInvoiceItem) {
+  return request('/invoice/item/add', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 编辑发票内容 */
+export async function updateInvoiceItem(params: API.UpdateInvoiceItem) {
+  return request('/invoice/item/update', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 删除发票内容 */
+export async function deleteInvoiceItem(id: string) {
+  return request('/invoice/item/detele', {
+    method: 'POST',
+    data: { id }
+  })
+}

+ 24 - 0
src/services/user/typings.d.ts

@@ -290,4 +290,28 @@ declare namespace API {
     id: string
     name: string
   }
+
+  type InvoiceList = {
+    id: string
+    name: string
+  }
+
+  type AddInvoiceItem = {
+    rate: string
+    name: string
+  }
+
+  type InvoicegroupItem = {
+    id: string
+    name: string
+    sort: string
+    enable: string
+  }
+
+  type UpdateInvoicegroupItem = InvoicegroupItem & { id: string }
+
+  type DeleteInvoiceItem = {
+    id: string
+    name: string
+  }
 }