|
|
@@ -150,6 +150,7 @@
|
|
|
<el-dropdown-item command="adjustBalance" v-hasPermi="['fulfiller:pool:edit']">余额增减</el-dropdown-item>
|
|
|
<el-dropdown-item v-if="scope.row.status !== 'disabled'" command="disable" divided style="color: #f56c6c" v-hasPermi="['fulfiller:pool:edit']">禁用账号</el-dropdown-item>
|
|
|
<el-dropdown-item v-else command="enable" divided style="color: #67c23a" v-hasPermi="['fulfiller:pool:edit']">启用账号</el-dropdown-item>
|
|
|
+ <el-dropdown-item command="violation" v-hasPermi="['fulfiller:pool:edit']">违规记录</el-dropdown-item>
|
|
|
<el-dropdown-item command="resetPwd" v-hasPermi="['fulfiller:pool:edit']">重置密码</el-dropdown-item>
|
|
|
</el-dropdown-menu>
|
|
|
</template>
|
|
|
@@ -366,11 +367,6 @@
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <!-- <el-table-column prop="type" label="操作" width="80">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-tag :type="['reward', fulfillerEnums.ActionType.ADD].includes(row.type) ? 'success' : 'danger'" size="small">{{ ['reward', fulfillerEnums.ActionType.ADD].includes(row.type) ? '增加' : '减少' }}</el-tag>
|
|
|
- </template>
|
|
|
- </el-table-column> -->
|
|
|
<el-table-column prop="target" label="关联项目" width="100">
|
|
|
<template #default="{ row }">
|
|
|
<el-tag type="info" size="small" effect="plain">{{ row.target === 'points' ? '积分' : '余额' }}</el-tag>
|
|
|
@@ -388,6 +384,27 @@
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="违规记录" name="violation">
|
|
|
+ <div class="tab-content-wrapper">
|
|
|
+ <el-table v-loading="logLoading" :data="violationLogData" stripe style="width: 100%" :header-cell-style="{background:'#f5f7fa', color:'#606266'}">
|
|
|
+ <el-table-column prop="violationTime" label="违规时间" width="180">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <div style="display: flex; align-items: center; gap: 5px;">
|
|
|
+ <el-icon color="#909399"><Timer /></el-icon>
|
|
|
+ <span>{{ row.violationTime }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="count" label="违规次数" width="120" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag type="danger" effect="plain" round v-if="row.count > 0">{{ row.count }} 次</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="reason" label="违规原因" show-overflow-tooltip />
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
</el-tabs>
|
|
|
</div>
|
|
|
</el-drawer>
|
|
|
@@ -463,16 +480,6 @@
|
|
|
<el-checkbox v-model="editDialog.form.authQual">专业资质认证</el-checkbox>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <el-form-item label="技能标签">
|
|
|
- <el-checkbox-group v-model="editDialog.form.tagIds">
|
|
|
- <el-checkbox v-for="t in allTags" :key="t.id" :label="t.id" :value="t.id">{{ t.name }}</el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="服务类型">
|
|
|
- <el-select v-model="editDialog.serviceTypesArray" multiple placeholder="请选择服务类型" style="width: 100%">
|
|
|
- <el-option v-for="item in serviceOptions" :key="item.id" :label="item.name" :value="String(item.id)" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
<span class="dialog-footer">
|
|
|
@@ -541,11 +548,6 @@
|
|
|
<el-option v-for="station in createDialog.stationOptions" :key="station.id" :label="station.name" :value="station.id" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="服务类型">
|
|
|
- <el-select v-model="createDialog.serviceTypesArray" multiple placeholder="请选择服务类型" style="width: 100%">
|
|
|
- <el-option v-for="item in serviceOptions" :key="item.id" :label="item.name" :value="String(item.id)" />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
<el-button @click="createDialog.visible = false">取消</el-button>
|
|
|
@@ -553,6 +555,32 @@
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
+ <!-- 违规记录弹窗 -->
|
|
|
+ <el-dialog v-model="violationDialog.visible" title="新增违规记录" width="450px">
|
|
|
+ <el-form :model="violationDialog.form" label-width="80px">
|
|
|
+ <el-form-item label="违规次数" required>
|
|
|
+ <el-input-number v-model="violationDialog.form.count" :min="1" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="违规时间" required>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="violationDialog.form.violationTime"
|
|
|
+ type="datetime"
|
|
|
+ placeholder="请选择违规时间"
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ style="width: 100%"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="违规原因" required>
|
|
|
+ <el-input v-model="violationDialog.form.reason" type="textarea" :rows="3" placeholder="请输入违规原因说明" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="violationDialog.visible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="submitViolation">确认提交</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
<!-- 积分调整弹窗 -->
|
|
|
<el-dialog v-model="pointsDialog.visible" title="修改积分" width="400px">
|
|
|
<el-form :model="pointsDialog.form" label-width="80px">
|
|
|
@@ -626,6 +654,8 @@ import {
|
|
|
changeStatus, resetPwd, reward, adjustPoints, adjustBalance,
|
|
|
listPointsLog, listBalanceLog, listRewardLog
|
|
|
} from '@/api/fulfiller/pool'
|
|
|
+import { addViolation, listViolationByFulfiller } from '@/api/fulfiller/violation'
|
|
|
+import type { FlfViolationVO } from '@/api/fulfiller/violation/types'
|
|
|
import { listSubOrderOnFulfiller } from '@/api/order/subOrder/index'
|
|
|
import { listOnStore as listServiceOnStore } from '@/api/service/list/index'
|
|
|
import type {
|
|
|
@@ -638,6 +668,7 @@ import type { FlfTagVO } from '@/api/fulfiller/tag/types'
|
|
|
import { listOnStore } from '@/api/system/areaStation'
|
|
|
import type { SysAreaStationOnStoreVo } from '@/api/system/areaStation/types'
|
|
|
import fulfillerEnums from '@/enums/fulfiller.json'
|
|
|
+import ImageUpload from '@/components/ImageUpload/index.vue'
|
|
|
|
|
|
const loading = ref(false)
|
|
|
const searchKey = ref('')
|
|
|
@@ -670,6 +701,7 @@ const qualImageUrlList = computed(() => {
|
|
|
const pointsLogData = ref<FlfPointsLogVO[]>([])
|
|
|
const balanceLogData = ref<FlfBalanceLogVO[]>([])
|
|
|
const rewardLogData = ref<FlfRewardLogVO[]>([])
|
|
|
+const violationLogData = ref<FlfViolationVO[]>([])
|
|
|
const serviceOrderData = ref<any[]>([])
|
|
|
const serviceOptions = ref<any[]>([])
|
|
|
const logLoading = ref(false)
|
|
|
@@ -806,8 +838,7 @@ const editDialog = reactive({
|
|
|
visible: false,
|
|
|
form: {} as FlfFulfillerForm,
|
|
|
cascaderValue: [] as any[],
|
|
|
- stationOptions: [] as SysAreaStationOnStoreVo[],
|
|
|
- serviceTypesArray: [] as string[]
|
|
|
+ stationOptions: [] as SysAreaStationOnStoreVo[]
|
|
|
})
|
|
|
|
|
|
const createDialog = reactive({
|
|
|
@@ -816,8 +847,7 @@ const createDialog = reactive({
|
|
|
name: '', phone: '', password: '', cityCode: '', cityName: '', stationId: undefined as any, gender: '0', workType: 'full_time'
|
|
|
},
|
|
|
cascaderValue: [] as any[],
|
|
|
- stationOptions: [] as SysAreaStationOnStoreVo[],
|
|
|
- serviceTypesArray: [] as string[]
|
|
|
+ stationOptions: [] as SysAreaStationOnStoreVo[]
|
|
|
})
|
|
|
|
|
|
const pointsDialog = reactive({
|
|
|
@@ -832,6 +862,16 @@ const balanceDialog = reactive({
|
|
|
form: { type: fulfillerEnums.ActionType.ADD, subType: 'admin_reward', amount: 0, reason: '' }
|
|
|
})
|
|
|
|
|
|
+const violationDialog = reactive({
|
|
|
+ visible: false,
|
|
|
+ fulfillerId: 0 as number | string,
|
|
|
+ form: {
|
|
|
+ count: 1,
|
|
|
+ violationTime: '',
|
|
|
+ reason: ''
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
const getStatusText = (status: string) => {
|
|
|
const map: Record<string, string> = { busy: '接单中', resting: '休息', disabled: '禁用', frozen: '冻结' }
|
|
|
return map[status] || '未知'
|
|
|
@@ -859,16 +899,18 @@ const handleTabClick = (tab: any) => {
|
|
|
const loadLogs = async (fulfillerId: string | number) => {
|
|
|
logLoading.value = true
|
|
|
try {
|
|
|
- const [pRes, bRes, rRes, sRes] = await Promise.all([
|
|
|
+ const [pRes, bRes, rRes, sRes, vRes] = await Promise.all([
|
|
|
listPointsLog(fulfillerId, { pageNum: 1, pageSize: 20 }),
|
|
|
listBalanceLog(fulfillerId, { pageNum: 1, pageSize: 20 }),
|
|
|
listRewardLog(fulfillerId, { pageNum: 1, pageSize: 20 }),
|
|
|
- listSubOrderOnFulfiller(fulfillerId)
|
|
|
+ listSubOrderOnFulfiller(fulfillerId),
|
|
|
+ listViolationByFulfiller({ fulfillerId, pageNum: 1, pageSize: 20 })
|
|
|
])
|
|
|
pointsLogData.value = pRes.rows || []
|
|
|
balanceLogData.value = bRes.rows || []
|
|
|
rewardLogData.value = rRes.rows || []
|
|
|
serviceOrderData.value = sRes.data || []
|
|
|
+ violationLogData.value = vRes.rows || []
|
|
|
} catch { /* ignore */ } finally {
|
|
|
logLoading.value = false
|
|
|
}
|
|
|
@@ -900,10 +942,8 @@ const handleEdit = (row: FlfFulfillerVO) => {
|
|
|
status: row.status,
|
|
|
authId: row.authId,
|
|
|
authQual: row.authQual,
|
|
|
- tagIds: row.tags ? row.tags.map(t => t.id) : [],
|
|
|
- serviceTypes: row.serviceTypes
|
|
|
+ tagIds: row.tags ? row.tags.map(t => t.id) : []
|
|
|
}
|
|
|
- editDialog.serviceTypesArray = row.serviceTypes ? row.serviceTypes.split(',') : []
|
|
|
// 根据cityCode构建级联选择器的值
|
|
|
editDialog.cascaderValue = []
|
|
|
editDialog.stationOptions = []
|
|
|
@@ -925,10 +965,11 @@ const handleEdit = (row: FlfFulfillerVO) => {
|
|
|
}
|
|
|
|
|
|
const handleCreate = () => {
|
|
|
- createDialog.form = { name: '', phone: '', password: '', cityCode: '', cityName: '', stationId: undefined, gender: '0', workType: 'full_time' }
|
|
|
+ createDialog.form = {
|
|
|
+ name: '', phone: '', password: '', cityCode: '', cityName: '', stationId: undefined, gender: '0', workType: 'full_time'
|
|
|
+ }
|
|
|
createDialog.cascaderValue = []
|
|
|
createDialog.stationOptions = []
|
|
|
- createDialog.serviceTypesArray = []
|
|
|
createDialog.visible = true
|
|
|
}
|
|
|
|
|
|
@@ -938,8 +979,7 @@ const submitCreate = async () => {
|
|
|
return
|
|
|
}
|
|
|
try {
|
|
|
- const submitForm = { ...createDialog.form, serviceTypes: createDialog.serviceTypesArray.join(',') };
|
|
|
- await addFulfiller(submitForm as FlfFulfillerForm)
|
|
|
+ await addFulfiller(createDialog.form as FlfFulfillerForm)
|
|
|
createDialog.visible = false
|
|
|
ElMessage.success('创建成功')
|
|
|
getList()
|
|
|
@@ -948,8 +988,7 @@ const submitCreate = async () => {
|
|
|
|
|
|
const saveEdit = async () => {
|
|
|
try {
|
|
|
- const submitForm = { ...editDialog.form, serviceTypes: editDialog.serviceTypesArray.join(',') };
|
|
|
- await updateFulfiller(submitForm)
|
|
|
+ await updateFulfiller(editDialog.form)
|
|
|
ElMessage.success('更新成功')
|
|
|
editDialog.visible = false
|
|
|
getList()
|
|
|
@@ -1012,9 +1051,32 @@ const handleCommand = async (cmd: string, row: FlfFulfillerVO) => {
|
|
|
await resetPwd(row.id, '123456')
|
|
|
ElMessage.success('密码重置成功')
|
|
|
} catch { /* handled by interceptor */ }
|
|
|
+ } else if (cmd === 'violation') {
|
|
|
+ violationDialog.fulfillerId = row.id
|
|
|
+ violationDialog.form = {
|
|
|
+ count: 1,
|
|
|
+ violationTime: new Date().toISOString().replace('T', ' ').split('.')[0],
|
|
|
+ reason: ''
|
|
|
+ }
|
|
|
+ violationDialog.visible = true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const submitViolation = async () => {
|
|
|
+ if (!violationDialog.form.violationTime || !violationDialog.form.reason) {
|
|
|
+ ElMessage.warning('请填写完整信息')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ await addViolation({
|
|
|
+ fulfiller: violationDialog.fulfillerId,
|
|
|
+ ...violationDialog.form
|
|
|
+ } as any)
|
|
|
+ ElMessage.success('添加违规记录成功')
|
|
|
+ violationDialog.visible = false
|
|
|
+ } catch { /* handled by interceptor */ }
|
|
|
+}
|
|
|
+
|
|
|
const submitPointsAdjust = async () => {
|
|
|
if (!pointsDialog.currentRow) return
|
|
|
try {
|