Browse Source

小程序-待办事项

dev
liujiangyong 1 year ago
parent
commit
3a21f20017
  1. 21
      api/app/lib/controllers/report/index.js
  2. 12
      api/app/lib/models/report.js
  3. 6
      scripts/1.3.1/schema/4.update_report.sql
  4. 217
      weapp/src/packages/patrol/index.jsx
  5. 18
      weapp/src/packages/patrol/index.scss
  6. 9
      weapp/src/packages/patrolView/index.jsx
  7. 10
      weapp/src/services/api.js

21
api/app/lib/controllers/report/index.js

@ -2,7 +2,7 @@
const { QueryTypes } = require('sequelize');
const moment = require('moment');
async function reportList (ctx) {
async function reportList(ctx) {
try {
const models = ctx.fs.dc.models;
const { limit, page, startTime, endTime, keyword, userId, reportType, isTop, asc, projectType, handleState = '', performerId = '', codeRoad } = ctx.query
@ -95,7 +95,8 @@ async function reportList (ctx) {
findOption.where.performerId = { $in: performerIds }
}
if (handleState) {
findOption.where.handleState = handleState
let handleStates = handleState.split(',')
findOption.where.handleState = { $in: handleStates }
}
if (codeRoad) {
findOption.where.codeRoad = codeRoad
@ -146,7 +147,7 @@ async function reportList (ctx) {
}
}
async function reportPosition (ctx) {
async function reportPosition(ctx) {
try {
const models = ctx.fs.dc.models;
const { startTime, endTime, userId, reportType } = ctx.query
@ -196,7 +197,7 @@ async function reportPosition (ctx) {
}
}
async function reportDetail (ctx) {
async function reportDetail(ctx) {
try {
const models = ctx.fs.dc.models;
const { reportId } = ctx.params
@ -218,7 +219,7 @@ async function reportDetail (ctx) {
}
}
async function reportHandle (ctx) {
async function reportHandle(ctx) {
try {
const { models } = ctx.fs.dc;
@ -248,7 +249,7 @@ async function reportHandle (ctx) {
}
}
async function createReport (ctx) {
async function createReport(ctx) {
try {
const { userId } = ctx.fs.api
const models = ctx.fs.dc.models;
@ -270,7 +271,7 @@ async function createReport (ctx) {
}
}
async function deleteReport (ctx) {
async function deleteReport(ctx) {
try {
const models = ctx.fs.dc.models;
const { reportId } = ctx.params;
@ -293,7 +294,7 @@ async function deleteReport (ctx) {
// TODO 小程序填写道路名称的时候的道路筛选 是一起都返回 还是不断传关键字搜索返回
async function spotPrepare (ctx) {
async function spotPrepare(ctx) {
try {
const { models } = ctx.fs.dc;
const sequelize = ctx.fs.dc.orm;
@ -365,7 +366,7 @@ async function spotPrepare (ctx) {
}
}
async function spotCheck (ctx) {
async function spotCheck(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
@ -447,7 +448,7 @@ async function spotCheck (ctx) {
}
}
}
async function spotCheckDetail (ctx) {
async function spotCheckDetail(ctx) {
const { models } = ctx.fs.dc
console.log('txc1', ctx.query)
const { startTime, endTime } = ctx.query

12
api/app/lib/models/report.js

@ -447,7 +447,17 @@ module.exports = dc => {
primaryKey: false,
field: "handle_opinions",
autoIncrement: false
}
},
handleAdvice: {
index: 6,
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: '管理员处理意见',
primaryKey: false,
field: "handle_advice",
autoIncrement: false
},
}, {
tableName: "report",
comment: "",

6
scripts/1.3.1/schema/4.update_report.sql

@ -0,0 +1,6 @@
ALTER TABLE "public"."report"
ADD COLUMN "handle_advice" varchar(1024);
COMMENT ON COLUMN "public"."report"."handle_state" IS '待处理 / 已指派 / 已处理 / 不处理';
COMMENT ON COLUMN "public"."report"."handle_advice" IS '管理员处理意见';

217
weapp/src/packages/patrol/index.jsx

@ -8,7 +8,7 @@ import VideoUpload from '../../components/uploads'
import request from '@/services/request';
import environment from '../../config';
import { getState } from '../../store/globalState';
import { postReport, getReportList, getReportDetail, delReport, getRoadSection, postImage, getProject, postHandle } from '@/services/api';
import { postReport, getReportList, getReportDetail, delReport, getRoadSection, postImage, getProject, postHandle, getAllDepUsers, getUsers } from '@/services/api';
import './index.scss';
import arrowIcon from '../../static/img/patrol/arrow-down.svg';
import dayjs from 'dayjs';
@ -25,6 +25,7 @@ const Index = () => {
const isPatrol = kind === 'patrol' || kind == 'conserve' ? true : false
const isRoad = kind === 'road' ? true : false
const isAnomaly = kind === 'anomaly' ? true : false
const noDel = wait === 'wait' || handle === 'handle'
const [reportType, setReportType] = useState(kind || 'patrol') //
const [projectType, setProjectType] = useState('') //
@ -60,7 +61,7 @@ const Index = () => {
const [handleId, setHandleId] = useState([])
const [video, setVideo] = useState('')
const [videoqn, setVideoqn] = useState([])
const [handleType, setHandleType] = useState('')
const [handleState, setHandleState] = useState('')
const [roadCodeHead, setRoadCodeHead] = useState('X')
const [roadCodeEnd, setRoadCodeEnd] = useState('')
@ -201,6 +202,12 @@ const Index = () => {
const [otherDescription, setOtherDescription] = useState('') //
const [isBeforeReport, setIsBeforeReport] = useState(false) // V1.1.0
const [isAppoint, setIsAppoint] = useState(true) // 指派 / 不处理
const [allDepUsers, setAllDepUsers] = useState([]) //
const [userList, setUserList] = useState([]) //
const [appointUser, setAppointUser] = useState(null) // userListindex
const [handleAdvice, setHandleAdvice] = useState('') //
const prjType =
isAnomaly ?
[
@ -282,7 +289,7 @@ const Index = () => {
setRoadSectionEnd(data.roadSectionEnd)
setAddress(data.address)
setContent(data.content)
setHandleType(data.handleState)
setHandleState(data.handleState)
setScenePic(data.scenePic ? data.scenePic.map(item => ({ url: imgUrl + item })) : [])
setHandlePic(data.handlePic ? data.handlePic.map(item => ({ url: imgUrl + item })) : [])
setConserveBeforePic(data.conserveBeforePic ? data.conserveBeforePic.map(item => ({ url: imgUrl + item })) : [])
@ -314,6 +321,9 @@ const Index = () => {
})
setConserveContent(nextContent)
setOtherDescription(data.otherDescription)
} else if (data.reportType === 'anomaly') {
setAppointUser(data.performerId)
setHandleAdvice(data.handleAdvice)
}
if (data.handleContent) {
setHandleCenter(data.handleContent)
@ -401,6 +411,19 @@ const Index = () => {
}
})
}
if (isSuperAdmin && kind === 'anomaly') {
request.get(getAllDepUsers()).then(res => {
if (res.statusCode === 200) {
setAllDepUsers(res.data)
}
})
request.get(getUsers()).then(res => {
if (res.statusCode === 200) {
const users = res.data.filter(u => u.phone !== 'SuperAdmin' && u.isAdmin)
setUserList(users)
}
})
}
}, [])
useEffect(() => {
@ -829,19 +852,36 @@ const Index = () => {
function handleOk() {
if (!canReport) { return }
let str = handleCenter.trim()
if (!str) {
Taro.showToast({ title: '请完善处理内容', icon: 'none' })
return
}
if (str.length > 50) {
Taro.showToast({ title: '内容字数不能超过50', icon: 'none' })
return
if (!isSuperAdmin) {
if (!str) {
Taro.showToast({ title: '请完善处理内容', icon: 'none' })
return
}
if (str.length > 50) {
Taro.showToast({ title: '内容字数不能超过50', icon: 'none' })
return
}
} else {
if (isAppoint && appointUser === null) {
Taro.showToast({ title: '请选择责任人', icon: 'none' })
return
}
}
let data = {
handleContent: str,
handlePic: handlePicPn,
handleState: '已处理'
let data = {}
if (isSuperAdmin) {
data = {
handleState: isAppoint ? '已指派' : '不处理',
performerId: userList[appointUser].id,
handleAdvice,
}
} else {
data = {
handleContent: str,
handlePic: handlePicPn,
handleState: '已处理'
}
}
Taro.showModal({
title: '提示',
content: '您要进行处理提交吗?',
@ -1399,43 +1439,122 @@ const Index = () => {
</view>
}
{
isView ?
isSuperAdmin &&
<AtButton type='primary' className='del-btn' onClick={deleteReport}>删除</AtButton>
:
<AtButton type='primary' className='sub-btn' onClick={report}>上报</AtButton>
!isPatrol && (handleState == '已处理' || wait == 'wait' || handle == 'handle') ? <>
{
isSuperAdmin && (wait === 'wait' || kind === 'handle') && <View className='appoint'>
{
handleState === '待处理' ? //
<>
<RadioGroup onChange={(e) => {
setIsAppoint(e.detail.value === '指派' ? true : false)
}}>
<Radio value='指派' checked={isAppoint} color='#0080EE' className='radio'>指派</Radio>
<Radio value='不处理' checked={!isAppoint} color='#0080EE' className='radio' style={{ marginLeft: 10 }}>不处理</Radio>
</RadioGroup>
{
isAppoint && <>
<View className='picker'>
<Text>责任人{appointUser !== null ? userList[appointUser]?.name : ''}</Text>
<Picker
mode='selector'
range={userList}
rangeKey='name'
onChange={e => setAppointUser(Number(e.detail.value))}
>
<Image src={arrowIcon} className='arrow' />
</Picker>
</View>
<Textarea
placeholder='请输入处理意见'
value={handleAdvice}
onInput={e => setHandleAdvice(e.target.value)}
disabled={isView && handleState !== '待处理'}
maxlength={1024}
/>
</>
}
</>
: //
<>
{/* {
handleState === '不处理' && <Text>
处理结果暂不进行处理
</Text>
} */}
{/* {
(handleState === '已指派' || handleState === '已处理') && <>
<View>处理意见</View>
<View>{handleAdvice}</View>
<View style={{ marginTop: 10 }}>责任人</View>
<View>{appointUser !== null ? allDepUsers.find(d => d.depId === userList[appointUser]?.departmentId)?.depName : ''}-{appointUser !== null ? userList[appointUser]?.name : ''}</View>
</>
} */}
</>
}
</View>
}
{
handleState !== '待处理' && <View style={{ backgroundColor: '#fff', padding: 10 }}>
{
isSuperAdmin && handleState === '不处理' && <Text>
处理结果暂不进行处理
</Text>
}
{
(!isSuperAdmin || (isSuperAdmin && (handleState === '已指派' || handleState === '已处理'))) && <>
<View>处理意见</View>
<View>{handleAdvice}</View>
</>
}
{
(isSuperAdmin && (handleState === '已指派' || handleState === '已处理')) && <>
<View style={{ marginTop: 10 }}>责任人</View>
<View>{appointUser !== null ? allDepUsers.find(d => d.depId === userList[appointUser]?.departmentId)?.depName : ''}-{appointUser !== null ? userList[appointUser]?.name : ''}</View>
</>
}
</View>
}
{
((isSuperAdmin && handleState == '已处理') || !isSuperAdmin) && <>
<View className='patrol-img'><Text style={{ color: 'red' }}>*</Text>处理内容</View>
<AtTextarea
placeholder='请输入处理内容'
value={handleCenter}
onChange={(v, e) => handleInput(e, 'wait')}
disabled={handle == 'handle' ? true : false}
maxLength={50}
/>
<View className='patrol-img'>
处理图片
{
handle == 'handle' || handleState == '已处理' ?
<View className='img-box'>
{handlePic.map(item => (
<Image className='img' src={item.url} onClick={() => handleImgClicks(undefined, item)} />
))}
</View> : handleState != '已处理' ?
<AtImagePicker
className='img-picker'
count={3 - handlePic.length}
showAddBtn={handlePic.length >= 3 ? false : true}
files={handlePic}
onChange={(files, operationType, index) => handleImgChange(files, operationType, index, 'wait')}
onImageClick={handleImgClick}
/> : ''
}
</View>
</>
}
{handle != 'handle' && handleState != '已处理' ? <AtButton type='primary' className='sub-btn' onClick={handleOk}>提交</AtButton> : ''}
</> : ''
}
{
!isPatrol && (handleType == '已处理' || wait == 'wait' || handle == 'handle') ? <view>
<view className='patrol-img'><text style={{ color: 'red' }}>*</text>处理内容</view>
<AtTextarea
title='处理内容:'
value={handleCenter}
onChange={(v, e) => handleInput(e, 'wait')}
disabled={handle == 'handle' ? true : false}
maxLength={50}
/>
<View className='patrol-img'>
处理图片
{
handle == 'handle' || handleType == '已处理' ?
<View className='img-box'>
{handlePic.map(item => (
<Image className='img' src={item.url} onClick={() => handleImgClicks(undefined, item)} />
))}
</View> : handleType != '已处理' ?
<AtImagePicker
className='img-picker'
count={3 - handlePic.length}
showAddBtn={handlePic.length >= 3 ? false : true}
files={handlePic}
onChange={(files, operationType, index) => handleImgChange(files, operationType, index, 'wait')}
onImageClick={handleImgClick}
/> : ''
}
{handle != 'handle' && handleType != '已处理' ? <AtButton type='primary' className='sub-btn' onClick={handleOk}>提交</AtButton> : ''}
</View>
</view> : ''
isView
? isSuperAdmin && !noDel && <AtButton type='primary' className='del-btn' onClick={deleteReport}>删除</AtButton>
: <AtButton type='primary' className='sub-btn' onClick={report}>上报</AtButton>
}
<AtMessage />
</View >

18
weapp/src/packages/patrol/index.scss

@ -281,4 +281,22 @@ page {
}
}
}
.appoint {
margin-top: 10px;
padding: 10px 20px;
background-color: #fff;
.picker {
margin: 10px 0;
display: flex;
justify-content: flex-start;
.arrow {
width: 24px;
height: 14px;
margin: 0 10px;
}
}
}
}

9
weapp/src/packages/patrolView/index.jsx

@ -16,6 +16,7 @@ import conserveActiveIcon from '../../static/img/patrolView/conserve-active.svg'
function Index() {
const userInfo = Taro.getStorageSync('userInfo') || {};
const isAdmin = userInfo && userInfo.username === 'SuperAdmin' ? true : false
const router = useRouter()
const { params: { filter, kind, } } = router
@ -76,7 +77,11 @@ function Index() {
if (typeSearch != '全部') {
handleState = typeSearch
} else {
handleState = isWait ? '待处理' : ishandle ? '已处理' : ''
handleState = isWait
? isAdmin ? '待处理' : '待处理,已指派'
: ishandle
? isAdmin ? '已处理,已指派,不处理' : '已处理'
: ''
}
const data = {
limit,
@ -87,7 +92,7 @@ function Index() {
reportType: isWait || ishandle ? 'anomaly' : reportType,
userId: filter === 'my' && !ishandle ? userInfo.id : '',
handleState: handleState,
performerId: isWait || ishandle ? userInfo.id : ''
performerId: (isWait || ishandle) && !isAdmin ? userInfo.id : '', //
}
request.get(getReportList(), data).then(res => {
Taro.hideLoading()

10
weapp/src/services/api.js

@ -7,6 +7,16 @@ export const getLogoutUrl = () => {
return `/logout`;
};
// 获取所有部门用户列表
export const getAllDepUsers = () => {
return `/allDepUsers`;
};
// 获取所有用户列表
export const getUsers = () => {
return `/user`;
};
// 巡查上报
export const postReport = () => {
return `/report`;

Loading…
Cancel
Save