ソースを参照

Merge branch 'dev1.0' of http://git.ycjcjy.com/civilized_city/pc-admin into dev1.0

fangmingyue 2 年 前
コミット
0149a8168a

+ 12
- 2
src/pages/check/components/LocTable.jsx ファイルの表示

@@ -2,7 +2,7 @@ import React from 'react';
2 2
 import { Link } from 'react-router-dom';
3 3
 import useBool from '@/utils/hooks/useBool';
4 4
 import { Table, Space, Button, Row, Col, Card } from 'antd';
5
-import { getTaCheckItem } from '@/service/tacheckitem';
5
+import { getTaCheckItem, exportTaCheckItem } from '@/service/tacheckitem';
6 6
 import QuList from './QuList';
7 7
 import LocForm from './LocForm';
8 8
 import styles from './style.module.less';
@@ -14,6 +14,7 @@ export default (props) => {
14 14
   const [curItem, setCurItem] = React.useState();
15 15
   const [loading, startLoading, stopLoading] = useBool();
16 16
   const [open, setOpen] = React.useState(false);
17
+  const [expLoading, startExpLoading, stopExpLoading] = useBool();
17 18
 
18 19
   const columns = [
19 20
     {
@@ -107,6 +108,15 @@ export default (props) => {
107 108
     setOpen(true);
108 109
   }
109 110
 
111
+  const onExport = () => {
112
+    startExpLoading();
113
+    exportTaCheckItem(checkId).then(() => {
114
+      stopExpLoading();
115
+    }).catch(() => {
116
+      stopExpLoading();
117
+    });
118
+  }
119
+
110 120
   const onChange = (item) => {
111 121
     const newList = list.map(x => x.itemId === item.itemId ? item : x);
112 122
     setList(newList);
@@ -130,7 +140,7 @@ export default (props) => {
130 140
   return (
131 141
     <Row gutter={24}>
132 142
       <Col span={12}>
133
-        <Card>
143
+        <Card extra={<Button loading={expLoading} type="primary" onClick={onExport}>导出</Button>}>
134 144
           <Table
135 145
             sticky
136 146
             summary={() => (

+ 3
- 3
src/pages/check/components/QuForm.jsx ファイルの表示

@@ -130,7 +130,7 @@ export default (props) => {
130 130
           />
131 131
         </Col>
132 132
         <Col span={6}>
133
-          {/* <ProFormSelect
133
+          <ProFormSelect
134 134
             initialValue={'+'}
135 135
             name="computeType"
136 136
             label="计分方式"
@@ -147,7 +147,7 @@ export default (props) => {
147 147
                 message: '请选择计分方式',
148 148
               },
149 149
             ]}
150
-          /> */}
150
+          />
151 151
         </Col>
152 152
         <Col span={6}>
153 153
           <ProFormDigit
@@ -255,8 +255,8 @@ export default (props) => {
255 255
                       <ProFormDigit
256 256
                         name="score"
257 257
                         label="计分"
258
-                        min={0}
259 258
                         help="计分"
259
+                        min={-999}
260 260
                         fieldProps={{ precision: 2 }}
261 261
                       />
262 262
                     </Col>

+ 2
- 1
src/pages/check/components/QuList.jsx ファイルの表示

@@ -13,7 +13,8 @@ export default (props) => {
13 13
   const [loading, startLoading, stopLoading] = useBool();
14 14
 
15 15
   const totalScore = React.useMemo(() => {
16
-    return list?.map((x) => x.maxScore).reduce((total, num) => total + num, 0);
16
+    const s = list?.map((x) => x.maxScore).reduce((total, num) => total + num, 0);
17
+    return Number(s || 0).toFixed(2);
17 18
   }, [list]);
18 19
 
19 20
   const columns = [

+ 2
- 1
src/pages/check/components/SurveyForm.jsx ファイルの表示

@@ -2,7 +2,7 @@ import React from 'react';
2 2
 import { Link } from 'react-router-dom';
3 3
 import { Button, Tabs, Form, Space } from 'antd';
4 4
 import { EditOutlined } from '@ant-design/icons';
5
-import { ModalForm, ProFormDigit, ProFormDependency } from '@ant-design/pro-components';
5
+import { ModalForm, ProFormDigit, ProFormText } from '@ant-design/pro-components';
6 6
 import { getTaCheckItem, postTaCheckItem } from '@/service/tacheckitem';
7 7
 
8 8
 const itemType = 'survey';
@@ -86,6 +86,7 @@ const SurveyForm = (props) => {
86 86
       )}
87 87
     >
88 88
       <ProFormDigit label="预收数量" name="num" min={1} fieldProps={{precision: 0}} />
89
+      <ProFormText label="文明用语" name="cultureTerm"  fieldProps={{precision: 0}} />
89 90
     </ModalForm>
90 91
   )
91 92
 }

+ 5
- 2
src/pages/check/index.jsx ファイルの表示

@@ -94,11 +94,14 @@ export default (props) => {
94 94
       dataIndex: "surveyScore",
95 95
       hideInSearch: true,
96 96
       render: (_, row) => {
97
+        const num = row.surveyNum || 0;
98
+        if (num === 0) return '-';
99
+
97 100
         const origin = row.surveyScore || 0;
98 101
         const percent = row.surveyScorePercent || 0;
99
-        const score = Number(origin * percent).toFixed(2);
102
+        const score = Number(origin / num * percent).toFixed(2);
100 103
 
101
-        return `${origin} * ${percent * 100}% = ${score}`;
104
+        return `${origin} / ${num} * ${percent * 100}% = ${score}`;
102 105
       },
103 106
     },
104 107
     {

+ 50
- 45
src/pages/checkAnswer/survey/index.jsx ファイルの表示

@@ -1,18 +1,21 @@
1
-import React from 'react';
2
-import Page from '@/components/Page';
3
-import { useNavigate, useSearchParams } from 'react-router-dom';
1
+import React from "react";
2
+import Page from "@/components/Page";
3
+import { useNavigate, useSearchParams } from "react-router-dom";
4 4
 import { queryTable, queryDict } from "@/utils/request";
5 5
 import { ProTable } from "@ant-design/pro-components";
6 6
 import { Button, notification } from "antd";
7
-import { getTaCheck } from '@/service/tacheck';
8
-import { getTaCheckAnswer, exportTaCheckAnswer } from '@/service/tacheckanswer';
9
-import useBool from '@/utils/hooks/useBool';
10
-import TargetLink from '@/components/TargetLink';
7
+import { getTaCheck } from "@/service/tacheck";
8
+import { getTaCheckAnswer, exportTaCheckAnswer } from "@/service/tacheckanswer";
9
+import useBool from "@/utils/hooks/useBool";
10
+import TargetLink from "@/components/TargetLink";
11 11
 
12
-const getCheck = queryDict(getTaCheck, { labelKey: 'title', valueKey: 'checkId' });
12
+const getCheck = queryDict(getTaCheck, {
13
+  labelKey: "title",
14
+  valueKey: "checkId",
15
+});
13 16
 const getAnswer = queryTable(getTaCheckAnswer);
14 17
 
15
-const addOnParams = { itemType: 'survey' };
18
+const addOnParams = { itemType: "survey" };
16 19
 
17 20
 export default (props) => {
18 21
   const [loading, startLoading, stopLoading] = useBool();
@@ -20,36 +23,36 @@ export default (props) => {
20 23
   const [notificationApi, contextHolder] = notification.useNotification();
21 24
   const navigate = useNavigate();
22 25
   const [searchParams] = useSearchParams();
23
-  
26
+
24 27
   const initialValues = React.useMemo(() => {
25
-    const checkId = searchParams.get('checkId');
26
-  
28
+    const checkId = searchParams.get("checkId");
29
+
27 30
     return {
28 31
       checkId,
29
-    }
32
+    };
30 33
   }, []);
31 34
 
32 35
   const goToDetail = (row) => {
33
-    navigate(`/checkAnswer/survey/detail?answerId=${row.answerId}&itemType=survey`)
34
-  }
36
+    navigate(
37
+      `/checkAnswer/survey/detail?answerId=${row.answerId}&itemType=survey`
38
+    );
39
+  };
35 40
 
36 41
   const columns = [
37 42
     {
38 43
       title: "模拟测评",
39 44
       dataIndex: "checkId",
40
-      valueType: 'select',
45
+      valueType: "select",
41 46
       request: getCheck,
42 47
       hideInTable: true,
43 48
       formItemProps: {
44
-        rules: [
45
-          { required: true, message: '请选择模拟测评' }
46
-        ]
47
-      }
49
+        rules: [{ required: true, message: "请选择模拟测评" }],
50
+      },
48 51
     },
49 52
     {
50 53
       title: "答题时间",
51 54
       dataIndex: "createDate",
52
-      valueType: 'date',
55
+      valueType: "date",
53 56
       hideInSearch: true,
54 57
     },
55 58
     {
@@ -80,38 +83,45 @@ export default (props) => {
80 83
       hideInSearch: true,
81 84
     },
82 85
     {
83
-      title: '操作',
86
+      title: "操作",
84 87
       hideInSearch: true,
85
-      key: 'options',
88
+      key: "options",
86 89
       render: (_, row) => {
87 90
         return (
91
+          // <a target="_blank" onClick={(row, e) => jumpPage(row, e)}>
92
+          //   详情
93
+          // </a>
88 94
           <TargetLink to={`/checkAnswer/survey/detail?answerId=${row.answerId}&itemType=survey`}>详情</TargetLink>
89
-        )
90
-      }
91
-    }
92
-  ]
93
-
95
+        );
96
+      },
97
+    },
98
+  ];
99
+  const jumpPage = (row, e) => {
100
+    e.target.href = `/checkAnswer/survey/detail?answerId=${row.answerId}&itemType=survey`;
101
+  };
94 102
   const beforeSearchSubmit = (params) => {
95 103
     paramsRef.current = params;
96 104
     return params;
97
-  }
105
+  };
98 106
 
99 107
   const onExport = () => {
100 108
     if (!paramsRef.current) {
101
-      notificationApi.warning({ message: '请先进行条件查询' });
102
-      return
109
+      notificationApi.warning({ message: "请先进行条件查询" });
110
+      return;
103 111
     }
104 112
 
105 113
     startLoading();
106 114
     exportTaCheckAnswer({
107 115
       ...paramsRef.current,
108 116
       ...addOnParams,
109
-    }).then(() => {
110
-      stopLoading();
111
-    }).catch(() => {
112
-      stopLoading();
113
-    });
114
-  }
117
+    })
118
+      .then(() => {
119
+        stopLoading();
120
+      })
121
+      .catch(() => {
122
+        stopLoading();
123
+      });
124
+  };
115 125
 
116 126
   return (
117 127
     <Page>
@@ -125,16 +135,11 @@ export default (props) => {
125 135
         beforeSearchSubmit={beforeSearchSubmit}
126 136
         form={{ ignoreRules: false, initialValues }}
127 137
         toolBarRender={() => [
128
-          <Button
129
-            key="1"
130
-            type="primary"
131
-            loading={loading}
132
-            onClick={onExport}
133
-          >
138
+          <Button key="1" type="primary" loading={loading} onClick={onExport}>
134 139
             导出
135 140
           </Button>,
136 141
         ]}
137 142
       />
138 143
     </Page>
139
-  )
140
-}
144
+  );
145
+};

+ 75
- 50
src/pages/issue/detail/components/BasicProfile.jsx ファイルの表示

@@ -1,61 +1,63 @@
1
-import React from 'react';
2
-import { Card, Descriptions, Badge } from 'antd';
3
-import dayjs from 'dayjs';
4
-import useBool from '@/utils/hooks/useBool';
5
-import { getTaIssueById } from '@/service/taissue';
6
-import { getSysOrgById } from '@/service/sysorg';
7
-import { processStatus } from '@/utils/biz';
8
-import AttachList from './AttachList';
1
+import React from "react";
2
+import { Card, Descriptions, Badge } from "antd";
3
+import dayjs from "dayjs";
4
+import useBool from "@/utils/hooks/useBool";
5
+import { getTaIssueById } from "@/service/taissue";
6
+import { getSysOrgById } from "@/service/sysorg";
7
+import { processStatus } from "@/utils/biz";
8
+import AttachList from "./AttachList";
9 9
 
10
-const yestoday = dayjs().subtract(1, 'day').format('YYYY-MM-DD');
11
-const fmDate = dt => !dt ? '-' : dayjs(dt).format('YYYY-MM-DD');
12
-const fmDateTime = dt => !dt ? '-' : dayjs(dt).format('YYYY-MM-DD HH:mm:ss');
13
-const getStatusLabel = val => (processStatus.filter(x => x.value == val)[0])?.label;
10
+const yestoday = dayjs().subtract(1, "day").format("YYYY-MM-DD");
11
+const fmDate = (dt) => (!dt ? "-" : dayjs(dt).format("YYYY-MM-DD"));
12
+const fmDateTime = (dt) =>
13
+  !dt ? "-" : dayjs(dt).format("YYYY-MM-DD HH:mm:ss");
14
+const getStatusLabel = (val) =>
15
+  processStatus.filter((x) => x.value == val)[0]?.label;
14 16
 
15 17
 export default (props) => {
16
-
17 18
   const { issueId, onIssueChange } = props;
18 19
 
19 20
   const [loading, startLoading, stopLoading] = useBool();
20 21
   const [detail, setDetail] = React.useState();
21 22
 
22
-  const [
23
-    isExpire,
24
-    status,
25
-  ] = React.useMemo(() => {
23
+  const [isExpire, status] = React.useMemo(() => {
26 24
     if (!detail) return [];
27 25
     return [
28
-      detail.processNode != '03' && yestoday > detail.expireDate,
29
-      processStatus.filter(x => x.value == detail.processNode)[0],
30
-    ]
26
+      detail.processNode != "03" && yestoday > detail.expireDate,
27
+      processStatus.filter((x) => x.value == detail.processNode)[0],
28
+    ];
31 29
   }, [detail]);
32 30
 
33 31
   React.useEffect(() => {
34 32
     if (issueId) {
35 33
       startLoading();
36
-      getTaIssueById(issueId).then((res) => {
37
-        if (onIssueChange) {
38
-          onIssueChange(res);
39
-        }
34
+      getTaIssueById(issueId)
35
+        .then((res) => {
36
+          if (onIssueChange) {
37
+            onIssueChange(res);
38
+          }
40 39
 
41
-        if (res.orgId) {
42
-          getSysOrgById(res.orgId).then(r => {
43
-            stopLoading();
44
-            setDetail({
45
-              ...res,
46
-              orgName: r.name
47
-            });
48
-          }).catch(() => {
40
+          if (res.orgId) {
41
+            getSysOrgById(res.orgId)
42
+              .then((r) => {
43
+                stopLoading();
44
+                setDetail({
45
+                  ...res,
46
+                  orgName: r.name,
47
+                });
48
+              })
49
+              .catch(() => {
50
+                stopLoading();
51
+                setDetail(res);
52
+              });
53
+          } else {
49 54
             stopLoading();
50 55
             setDetail(res);
51
-          });
52
-        } else {
56
+          }
57
+        })
58
+        .catch((er) => {
53 59
           stopLoading();
54
-          setDetail(res);
55
-        }
56
-      }).catch(er => {
57
-        stopLoading();
58
-      });
60
+        });
59 61
     }
60 62
   }, [issueId]);
61 63
   return (
@@ -63,18 +65,41 @@ export default (props) => {
63 65
       <Descriptions layout="vertical" column={3} bordered>
64 66
         <Descriptions.Item label="点位">{detail?.locName}</Descriptions.Item>
65 67
         <Descriptions.Item label="地址">{detail?.addr}</Descriptions.Item>
66
-        <Descriptions.Item label="上报时间">{fmDate(detail?.createDate)}</Descriptions.Item>
68
+        <Descriptions.Item label="上报时间">
69
+          {fmDate(detail?.createDate)}
70
+        </Descriptions.Item>
67 71
         <Descriptions.Item label="上报人">{detail?.userName}</Descriptions.Item>
68
-        <Descriptions.Item label="问题类型">{detail?.typeName}</Descriptions.Item>
72
+        <Descriptions.Item label="问题类型">
73
+          {detail?.typeName}
74
+        </Descriptions.Item>
75
+        <Descriptions.Item label="问题来源">
76
+          {detail?.sourceType == "check"
77
+            ? "实地检测"
78
+            : detail?.sourceType == "feedback"
79
+            ? "市民上报"
80
+            : detail?.sourceType == "inspector"
81
+            ? "日常督查"
82
+            : ""}
83
+        </Descriptions.Item>
69 84
         <Descriptions.Item label="流程状态">
70
-          {
71
-            isExpire ? <Badge status="error" text="已逾期" /> : <Badge status={status?.badge} text={status?.label} />
72
-          }
85
+          {isExpire ? (
86
+            <Badge status="error" text="已逾期" />
87
+          ) : (
88
+            <Badge status={status?.badge} text={status?.label} />
89
+          )}
90
+        </Descriptions.Item>
91
+        <Descriptions.Item label="截止日期">
92
+          {fmDate(detail?.expireDate)}
93
+        </Descriptions.Item>
94
+        <Descriptions.Item label="责任单位" span={2}>
95
+          {detail?.orgName}
96
+        </Descriptions.Item>
97
+        <Descriptions.Item label="办结时间">
98
+          {fmDateTime(detail?.endDate)}
99
+        </Descriptions.Item>
100
+        <Descriptions.Item label="交办次数" span={2}>
101
+          {detail?.processNum}
73 102
         </Descriptions.Item>
74
-        <Descriptions.Item label="截止日期">{fmDate(detail?.expireDate)}</Descriptions.Item>
75
-        <Descriptions.Item label="责任单位" span={2}>{detail?.orgName}</Descriptions.Item>
76
-        <Descriptions.Item label="办结时间">{fmDateTime(detail?.endDate)}</Descriptions.Item>
77
-        <Descriptions.Item label="交办次数" span={2}>{detail?.processNum}</Descriptions.Item>
78 103
         <Descriptions.Item label="问题描述" span={3}>
79 104
           <div dangerouslySetInnerHTML={{ __html: detail?.content }}></div>
80 105
         </Descriptions.Item>
@@ -83,5 +108,5 @@ export default (props) => {
83 108
         </Descriptions.Item>
84 109
       </Descriptions>
85 110
     </Card>
86
-  )
87
-}
111
+  );
112
+};

+ 43
- 4
src/pages/issue/index.jsx ファイルの表示

@@ -1,6 +1,6 @@
1 1
 // 此页面包含两个接口  后端需要注意
2 2
 import React from "react";
3
-import { Button, Badge } from "antd";
3
+import { Button, Badge, Popconfirm } from "antd";
4 4
 import { useNavigate } from "react-router-dom";
5 5
 import List from "@/components/Page/List";
6 6
 import {
@@ -8,6 +8,7 @@ import {
8 8
   getTaOrgIssue,
9 9
   exportTaIssue,
10 10
   exportTaOrgIssue,
11
+  deleteTaOrgIssue,
11 12
 } from "@/service/taissue";
12 13
 import { getTdIssueType } from "@/service/tdissuetype";
13 14
 
@@ -32,6 +33,8 @@ const getTdList = queryDict(getTdIssueType, {
32 33
 
33 34
 const yestoday = dayjs().subtract(1, "day").format("YYYY-MM-DD");
34 35
 export default (props) => {
36
+  const issueIdRef = React.useRef();
37
+
35 38
   const [loading, startLoading, stopLoading] = useBool();
36 39
   const [loading1, startLoading1, stopLoading1] = useBool();
37 40
   const navigate = useNavigate();
@@ -59,6 +62,23 @@ export default (props) => {
59 62
         return <span>{row.typeName}</span>;
60 63
       },
61 64
     },
65
+    {
66
+      title: "问题来源",
67
+      dataIndex: "sourceType",
68
+      valueType: "select",
69
+      valueEnum: {
70
+        check: "实地测评",
71
+        feedback: "市民上报",
72
+        inspector: "日常督查",
73
+      },
74
+      search: {
75
+        transform: (value) => {
76
+          return {
77
+            'sourceType2': value,
78
+          };
79
+        },
80
+      },
81
+    },
62 82
     {
63 83
       title: "创建时间",
64 84
       dataIndex: "createdAt",
@@ -141,7 +161,6 @@ export default (props) => {
141 161
     {
142 162
       title: "上报人",
143 163
       dataIndex: "userName",
144
-      // hideInSearch: true,
145 164
     },
146 165
     {
147 166
       title: "办结时间",
@@ -186,16 +205,36 @@ export default (props) => {
186 205
     };
187 206
     return params;
188 207
   };
189
-
208
+  const handleDelete = (row) => {
209
+    deleteTaOrgIssue(row.issueId).then(() => {
210
+      issueIdRef.current.reload();
211
+    });
212
+  };
190 213
   return (
191 214
     <List
215
+      ref={issueIdRef}
192 216
       rowKey="issueId"
193 217
       request={request}
194 218
       columns={columns}
195 219
       params={params}
196 220
       beforeSearchSubmit={beforeSearchSubmit}
197 221
       optionRender={(_, row) => [
198
-        <TargetLink key="detail" to={`/issue/detail?id=${row.issueId}`}>详情</TargetLink>,
222
+        <>
223
+          <TargetLink key="detail" to={`/issue/detail?id=${row.issueId}`}>
224
+            详情
225
+          </TargetLink>
226
+          <Popconfirm
227
+            key="delete"
228
+            title="您是否确认删除 ?"
229
+            onConfirm={() => handleDelete(row)}
230
+            okText="确定"
231
+            cancelText="取消"
232
+          >
233
+            <Button style={{ padding: 0 }} danger type="link">
234
+              删除
235
+            </Button>
236
+          </Popconfirm>
237
+        </>,
199 238
       ]}
200 239
       toolBarRender={() => [
201 240
         <Button key="1" type="primary" loading={loading} onClick={onExport}>

+ 4
- 1
src/service/tacheckitem.js ファイルの表示

@@ -32,4 +32,7 @@ export const deleteTaCheckItem = (id) => request(`/api/taCheckItem/${id}`, { met
32 32
  * @param {*} typeId 
33 33
  * @returns 
34 34
  */
35
-export const getByCheckId = (checkId, typeId) => request(`/api/taCheck/${checkId}/item/${typeId}`)
35
+export const getByCheckId = (checkId, typeId) => request(`/api/taCheck/${checkId}/item/${typeId}`)
36
+
37
+
38
+export const exportTaCheckItem = (checkId) => request(`/api/taCheck/${checkId}/loc/export`, { method: 'post', download: true });

+ 2
- 0
src/service/taissue.js ファイルの表示

@@ -34,6 +34,8 @@ export const putTaIssue = (id, data) => request(`/api/taIssue/${id}`, { data, me
34 34
  * 通过主键删除数据
35 35
  */
36 36
 export const deleteTaIssue = (id) => request(`/api/taIssue/${id}`, { method: 'delete' });
37
+export const deleteTaOrgIssue = (id) => request(`/api/taOrgIssue/${id}`, { method: 'delete' });
38
+
37 39
 
38 40
 /*
39 41
  * 导出

+ 1
- 1
src/utils/request.js ファイルの表示

@@ -52,7 +52,7 @@ instance.interceptors.response.use(
52 52
 
53 53
     const { data, config } = response;
54 54
 
55
-    if (config.download && !data.code) {
55
+    if (config.download && !data?.code) {
56 56
       return downloadBlob(response, "下载文件");
57 57
     }
58 58