Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
20 files modified
1 files renamed
2 files deleted
15 files added
| | |
| | | }); |
| | | }; |
| | | |
| | | export const getUserListApi = deptId => { |
| | | return request({ |
| | | url: '/blade-system/user/page', |
| | | // url: '/blade-system/user/user-list', |
| | | method: 'get', |
| | | params: { |
| | | current: 1, |
| | | size: 999, |
| | | deptId, |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | export const remove = ids => { |
| | | return request({ |
| | | url: '/blade-system/user/remove', |
| New file |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close> |
| | | <el-form ref="formRef" :model="formData" :rules="rules" :disabled="dialogReadonly" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="fwDeviceDTO.deviceName"> |
| | | <el-input v-model="formData.fwDeviceDTO.deviceName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备类型" prop="fwDeviceDTO.deviceType"> |
| | | <el-select v-model="formData.fwDeviceDTO.deviceType" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备属性" prop="fwDeviceDTO.deviceAtt"> |
| | | <el-select v-model="formData.fwDeviceDTO.deviceAtt" placeholder="请选择" clearable> |
| | | <el-option |
| | | v-for="item in dictObj.deviceAtt" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="型号" prop="fwDeviceDTO.deviceModel"> |
| | | <el-input v-model="formData.fwDeviceDTO.deviceModel" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="规格" prop="fwDeviceDTO.deviceSpecification"> |
| | | <el-input |
| | | v-model="formData.fwDeviceDTO.deviceSpecification" |
| | | maxlength="50" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="生产厂商" prop="fwDeviceDTO.manufacturer"> |
| | | <el-input v-model="formData.fwDeviceDTO.manufacturer" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="出库去向" prop="stockOutDestination"> |
| | | <el-input v-model="formData.stockOutDestination" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="来源" prop="fwDeviceDTO.source"> |
| | | <el-input v-model="formData.fwDeviceDTO.source" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="用途" prop="fwDeviceTrackDTO.purpose"> |
| | | <el-input v-model="formData.fwDeviceTrackDTO.purpose" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="所属部门" prop="fwDeviceDTO.ownerDept"> |
| | | <el-tree-select |
| | | v-model="formData.fwDeviceDTO.ownerDept" |
| | | node-key="id" |
| | | :data="deptTree" |
| | | :props="treeProps" |
| | | check-strictly |
| | | @change="getUserList" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="负责人" prop="fwDeviceTrackDTO.charger"> |
| | | <el-select |
| | | v-model="formData.fwDeviceTrackDTO.charger" |
| | | placeholder="请选择" |
| | | :disabled="!formData.fwDeviceDTO.ownerDept" |
| | | clearable |
| | | > |
| | | <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系电话" prop="fwDeviceTrackDTO.contactPhone"> |
| | | <el-input v-model="formData.fwDeviceTrackDTO.contactPhone" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系电话" prop="fwDeviceTrackDTO.contactPhone"> |
| | | <el-input v-model="formData.fwDeviceTrackDTO.contactPhone" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | v-if="!dialogReadonly" |
| | | type="primary" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fwDeviceDetailApi, fwDeviceSubmitApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import { getUserListApi } from '@/api/system/user' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | |
| | | const initForm = () => ({ |
| | | 'fwDeviceDTO': { |
| | | 'deviceAtt': '', |
| | | 'deviceModel': '', |
| | | 'deviceName': '', |
| | | 'deviceSpecification': '', |
| | | 'deviceType': '', |
| | | 'manufacturer': '', |
| | | 'remark': '', |
| | | 'source': '', |
| | | }, |
| | | 'fwDeviceTrackDTO': { |
| | | 'charger': '', |
| | | 'purpose': '', |
| | | 'contactPhone': '', |
| | | 'deptName': '', |
| | | 'outTarget': '', |
| | | 'outTime': '', |
| | | }, |
| | | }) |
| | | const treeProps = { |
| | | label: 'name', |
| | | children: 'children', |
| | | } |
| | | |
| | | const dictObj = inject('dictObj') |
| | | const deptTree = inject('deptTree') |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '编辑' |
| | | } else if (dialogMode.value === 'view') { |
| | | return '查看' |
| | | } else { |
| | | return '新增' |
| | | } |
| | | }) |
| | | |
| | | const rules = { |
| | | deviceName: fieldRules(true, 50), |
| | | deviceType: fieldRules(true, 0), |
| | | deviceAtt: fieldRules(true, 0), |
| | | deviceModel: fieldRules(true, 50), |
| | | deviceSpecification: fieldRules(true, 50), |
| | | manufacturer: fieldRules(true, 50), |
| | | stockOutDestination: fieldRules(true, 50), |
| | | source: fieldRules(true, 50), |
| | | purpose: fieldRules(true, 50), |
| | | ownerDept: fieldRules(true, 50), |
| | | charger: fieldRules(true, 0), |
| | | } |
| | | |
| | | const userList = ref([]) |
| | | function getUserList(val) { |
| | | formData.value.charger = '' |
| | | if (val) { |
| | | getUserListApi(val).then(res => { |
| | | userList.value = res.data.data.records |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await fwDeviceSubmitApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await fwDeviceDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = row |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="名称" prop="deviceName"> |
| | | <el-input v-model="searchParams.deviceName" placeholder="请输入" clearable @clear="getList" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="类型" prop="deviceType"> |
| | | <el-input v-model="searchParams.deviceType" placeholder="请输入" clearable @clear="getList" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="handleAdd">新增</el-button> |
| | | </div> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="deviceName" label="名称" /> |
| | | <el-table-column prop="deviceType" label="类型" /> |
| | | <el-table-column prop="deviceModel" label="设备型号" /> |
| | | <el-table-column prop="deviceSpecification" label="规格" /> |
| | | <el-table-column label="操作"> |
| | | <template v-slot="{ row }"> |
| | | <el-link @click="handleView(row)" type="primary">查看</el-link> |
| | | <el-link @click="handleEdit(row)" type="warning">编辑</el-link> |
| | | <el-link @click="handleDelete(row)" type="danger">删除</el-link> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <div> |
| | | <el-pagination |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" @success="getList" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { fwDevicePageApi, fwDeviceRemoveApi } from '@/views/basicManage/deviceStock/fwDevice' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { getDeptTree } from '@/api/system/dept' |
| | | |
| | | const initSearchParams = () => ({ |
| | | deviceName: '', // 设备名称 |
| | | deviceType: '', // 设备类型 |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dictObj = ref({ |
| | | deviceType: [], |
| | | deviceAtt: [], |
| | | }) |
| | | const deptTree = ref([]) |
| | | |
| | | provide('dictObj', dictObj) |
| | | provide('deptTree', deptTree) |
| | | // 获取列表 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await fwDevicePageApi(searchParams.value) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 查询 |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 重置查询 |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 查看 |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | // 编辑 |
| | | function handleEdit(row) { |
| | | dialogRef.value?.open({ mode: 'edit', row: { ...row } }) |
| | | } |
| | | |
| | | // 删除 |
| | | async function handleDelete(row) { |
| | | await ElMessageBox.confirm('确认删除该设备吗?', '提示', { type: 'warning' }) |
| | | await fwDeviceRemoveApi({ ids: row.id }) |
| | | ElMessage.success('删除成功') |
| | | getList() |
| | | } |
| | | |
| | | // 获取字典 |
| | | function getDictList() { |
| | | getDictionaryByCode('deviceType,deviceAtt').then(res => { |
| | | dictObj.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | // 获取部门树 |
| | | function getDeptTreeFun() { |
| | | getDeptTree().then(res => { |
| | | deptTree.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | // 新增 |
| | | function handleAdd() { |
| | | dialogRef.value?.open({ mode: 'add' }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | getDictList() |
| | | getDeptTreeFun() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 查list |
| | | export const fwDevicePageApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDevice/page`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 增加或更新 |
| | | export const fwDeviceSubmitApi = data => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDevice/submit`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | //删除 |
| | | export const fwDeviceRemoveApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDevice/remove`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | //详情 |
| | | export const fwDeviceDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/device/fwDevice/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| New file |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close> |
| | | <el-form ref="formRef" :model="formData" :rules="rules" :disabled="dialogReadonly" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="无人机名称" prop="droneName"> |
| | | <el-input v-model="formData.droneName" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="区域" prop="areaCode"> |
| | | <el-input v-model="formData.areaCode" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备类型" prop="droneType"> |
| | | <el-input v-model="formData.droneType" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="告警类型" prop="alarmType"> |
| | | <el-input v-model="formData.alarmType" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="告警时间" prop="alarmTime"> |
| | | <el-input v-model="formData.alarmTime" maxlength="50" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="触发原因" prop="triggerReason"> |
| | | <el-input v-model="formData.triggerReason" maxlength="200" placeholder="请输入" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button> |
| | | <el-button |
| | | v-if="!dialogReadonly" |
| | | type="primary" |
| | | :loading="submitting" |
| | | :disabled="submitting" |
| | | @click="handleSubmit" |
| | | > |
| | | 确定 |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, ref } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { fieldRules } from '@ztzf/utils' |
| | | import { fwDroneAlarmRecordDetailApi, fwDroneAlarmRecordSubmitApi } from './fwDroneAlarmRecord' |
| | | |
| | | const initForm = () => ({ |
| | | // 表单默认值 |
| | | id: '', // 主键id |
| | | alarmTime: '', // 告警时间 |
| | | alarmType: '', // 告警类型 |
| | | areaCode: '', // 区域 |
| | | droneName: '', // 无人机名称 |
| | | droneType: '', // 设备类型 |
| | | triggerReason: '', // 触发原因 |
| | | }) |
| | | |
| | | const emit = defineEmits(['success']) |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = ref(false) // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const submitting = ref(false) |
| | | const dialogReadonly = computed(() => dialogMode.value === 'view') |
| | | const dialogTitle = computed(() => { |
| | | if (dialogMode.value === 'edit') { |
| | | return '编辑' |
| | | } else if (dialogMode.value === 'view') { |
| | | return '查看' |
| | | } else { |
| | | return '新增' |
| | | } |
| | | }) |
| | | |
| | | const rules = { |
| | | droneName: fieldRules(true, 50), |
| | | areaCode: fieldRules(true, 50), |
| | | droneType: fieldRules(true, 50), |
| | | alarmType: fieldRules(true, 50), |
| | | alarmTime: fieldRules(true, 50), |
| | | triggerReason: fieldRules(false, 200), |
| | | } |
| | | |
| | | // 关闭弹框 |
| | | function handleCancel() { |
| | | visible.value = false |
| | | } |
| | | |
| | | // 提交新增/编辑 |
| | | async function handleSubmit() { |
| | | const isValid = await formRef.value?.validate().catch(() => false) |
| | | if (!isValid) return |
| | | submitting.value = true |
| | | try { |
| | | await fwDroneAlarmRecordSubmitApi(formData.value) |
| | | ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功') |
| | | visible.value = false |
| | | emit('success') |
| | | } finally { |
| | | submitting.value = false |
| | | } |
| | | } |
| | | |
| | | // 加载详情 |
| | | async function loadDetail() { |
| | | if (!formData.value.id) return |
| | | const res = await fwDroneAlarmRecordDetailApi({ id: formData.value.id }) |
| | | formData.value = res?.data?.data ?? {} |
| | | } |
| | | |
| | | // 关闭后重置 |
| | | function handleClosed() { |
| | | formData.value = initForm() |
| | | } |
| | | |
| | | // 打开弹框 |
| | | async function open({ mode, row } = {}) { |
| | | dialogMode.value = mode || 'add' |
| | | formData.value = row |
| | | visible.value = true |
| | | if (dialogMode.value === 'add') { |
| | | formData.value = initForm() |
| | | } else { |
| | | await loadDetail() |
| | | } |
| | | } |
| | | |
| | | defineExpose({ open }) |
| | | </script> |
| New file |
| | |
| | | <template> |
| | | <basic-container> |
| | | <el-form ref="queryParamsRef" :model="searchParams"> |
| | | <el-row :gutter="16"> |
| | | <el-col :span="4"> |
| | | <el-form-item label="无人机名称" prop="droneName"> |
| | | <el-input v-model="searchParams.droneName" placeholder="请输入" clearable @clear="getList" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="区域" prop="areaCode"> |
| | | <el-input v-model="searchParams.areaCode" placeholder="请输入" clearable @clear="getList" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="设备类型" prop="droneType"> |
| | | <el-select v-model="searchParams.droneType" placeholder="请选择" clearable @clear="getList"> |
| | | <el-option |
| | | v-for="item in dictObj.deviceType" |
| | | :key="item.dictKey" |
| | | :label="item.dictValue" |
| | | :value="item.dictKey" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button @click="resetForm">重置</el-button> |
| | | <el-button type="primary" @click="handleSearch">查询</el-button> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column type="index" width="60" label="序号" /> |
| | | <el-table-column prop="droneName" label="无人机名称" /> |
| | | <el-table-column prop="droneSerialNo" label="无人机序列号" /> |
| | | <el-table-column prop="alarmTime" label="告警时间" /> |
| | | <el-table-column prop="areaCode" label="区域" /> |
| | | <el-table-column prop="triggerReason" label="触发原因" /> |
| | | <el-table-column prop="deviceName" label="侦测反制设备" /> |
| | | <el-table-column prop="droneType" label="设备类型"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDeviceTypeName(row.droneType) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="deviceCode" label="设备编码"/> |
| | | <el-table-column label="设备状态"> |
| | | <template v-slot="{ row }"> |
| | | {{ getDeviceStatus(row) }} |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="操作">--> |
| | | <!-- <template v-slot="{ row }">--> |
| | | <!-- <el-link @click="handleView(row)" type="primary">查看</el-link>--> |
| | | <!-- </template>--> |
| | | <!-- </el-table-column>--> |
| | | </el-table> |
| | | |
| | | <div> |
| | | <el-pagination |
| | | v-model:current-page="searchParams.current" |
| | | v-model:page-size="searchParams.size" |
| | | :total="total" |
| | | @change="getList" |
| | | /> |
| | | </div> |
| | | |
| | | <FormDiaLog ref="dialogRef" /> |
| | | </basic-container> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz' |
| | | import { fwDroneAlarmRecordPageApi } from './fwDroneAlarmRecord' |
| | | import FormDiaLog from './FormDiaLog.vue' |
| | | |
| | | const initSearchParams = () => ({ |
| | | droneName: '', // 无人机名称 |
| | | areaCode: '', // 区域 |
| | | droneType: '', // 设备类型 |
| | | current: 1, // 当前页 |
| | | size: 10, // 每页大小 |
| | | }) |
| | | const searchParams = ref(initSearchParams()) // 查询参数 |
| | | const total = ref(0) // 总条数 |
| | | const loading = ref(false) // 列表加载中 |
| | | const list = ref([]) // 列表数据 |
| | | const queryParamsRef = ref(null) // 查询表单实例 |
| | | const dialogRef = ref(null) // 弹框实例 |
| | | const dictObj = ref({ |
| | | deviceType: [], |
| | | }) |
| | | const deviceTypeMap = computed(() => { |
| | | const map = new Map() |
| | | dictObj.value.deviceType.forEach(item => { |
| | | map.set(item.dictKey, item.dictValue) |
| | | }) |
| | | return map |
| | | }) |
| | | |
| | | // 获取列表 |
| | | async function getList() { |
| | | loading.value = true |
| | | try { |
| | | const res = await fwDroneAlarmRecordPageApi(searchParams.value) |
| | | list.value = res?.data?.data?.records ?? [] |
| | | total.value = res?.data?.data?.total ?? 0 |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | // 查询 |
| | | function handleSearch() { |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 重置查询 |
| | | function resetForm() { |
| | | queryParamsRef.value?.resetFields() |
| | | searchParams.value.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | // 查看 |
| | | function handleView(row) { |
| | | dialogRef.value?.open({ mode: 'view', row: { ...row } }) |
| | | } |
| | | |
| | | function getDeviceStatus(row) { |
| | | return row.deviceStatus ?? row.status ?? '-' |
| | | } |
| | | |
| | | function getDeviceTypeName(value) { |
| | | return deviceTypeMap.value.get(value) || value || '-' |
| | | } |
| | | |
| | | // 获取字典 |
| | | function getDictList() { |
| | | getDictionaryByCode('deviceType').then(res => { |
| | | dictObj.value = res.data.data |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | getDictList() |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | import request from '@/axios' |
| | | |
| | | // 查list |
| | | export const fwDroneAlarmRecordPageApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/record/fwDroneAlarmRecord/page`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | // 增加或更新 |
| | | export const fwDroneAlarmRecordSubmitApi = data => { |
| | | return request({ |
| | | url: `/drone-fw/record/fwDroneAlarmRecord/submit`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | //删除 |
| | | export const fwDroneAlarmRecordRemoveApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/record/fwDroneAlarmRecord/remove`, |
| | | method: 'post', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | //详情 |
| | | export const fwDroneAlarmRecordDetailApi = params => { |
| | | return request({ |
| | | url: `/drone-fw/record/fwDroneAlarmRecord/detail`, |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | |
| | | export function fieldRules(required, max) { |
| | | const trigger = ['blur', 'change'] |
| | | return [ |
| | | required ? { required: true, message: max ? '请输入' : '请选择', trigger } : {}, |
| | | max ? { max, message: `长度不超过${max}`, trigger } : {}, |
| | | ] |
| | | } |
| | |
| | | // 用户登录接口 |
| | | export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | url: '/auth/login', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': tenantId, |
| | |
| | | 'Captcha-Key': key, |
| | | 'Captcha-Code': code, |
| | | }, |
| | | params: { |
| | | data: { |
| | | tenantId, |
| | | username, |
| | | password, |
| | | checkCode:'', |
| | | mobile: false, |
| | | grant_type: 'password', |
| | | scope: 'all', |
| | | type, |
| | |
| | | } |
| | | export const getUserInfo = () => { |
| | | return request({ |
| | | url: '/blade-system/user/info', |
| | | url: '/system/user/getInfo', |
| | | method: 'get', |
| | | }); |
| | | }; |
| | | export const updateInfo = row => { |
| | | return request({ |
| | | url: '/blade-system/user/update-info', |
| | | url: '/system/user/profile/update', |
| | | method: 'post', |
| | | data: row, |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 微信登录接口 |
| | | export const loginByWechat = (code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': '000000', |
| | | }, |
| | | params: { |
| | | tenantId: '000000', |
| | | code, |
| | | grant_type: 'wechat', |
| | | scope: 'all', |
| | | type: 'wechat', |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 发送通话信息 |
| | | export const sendVoiceCallApi = (data) => { |
| | | return request({ |
| | |
| | | // 开发环境这里改为自己的 |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | // VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | VITE_API_BASE_URL: 'http://218.202.104.82:8200', |
| | | // VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | |
| | | |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | |
| | | { |
| | | "easycom": { |
| | | "custom": { |
| | | "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue" |
| | | } |
| | | }, |
| | | "pages": [ |
| | | { |
| | | "path": "pages/work/index", |
| | | "style": { |
| | | "navigationBarTitleText": "事件工单", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/voiceCall/index", |
| | | "style": { |
| | | "navigationBarTitleText": "通话", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/map/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | "easycom": { |
| | | "custom": { |
| | | "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue" |
| | | } |
| | | }, |
| | | "pages": [ |
| | | { |
| | | "path": "pages/work/index", |
| | | "style": { |
| | | "navigationBarTitleText": "事件工单", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/voiceCall/index", |
| | | "style": { |
| | | "navigationBarTitleText": "通话", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/map/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | |
| | | { |
| | | "path": "pages/user/index", |
| | | "style": { |
| | | "navigationBarTitleText": "我的", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/login/index", |
| | | "style": { |
| | | "navigationBarTitleText": "登录页", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | | { |
| | | "root": "subPackages", |
| | | "pages": [ |
| | | { |
| | | "path": "404/index", |
| | | "style": { |
| | | "navigationBarTitleText": "404", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/index", |
| | | "style": { |
| | | "navigationBarTitleText": "工单详情" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/addWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "新建工单" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/mapWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图展示", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/infos/index", |
| | | "style": { |
| | | "navigationBarTitleText": "个人资料" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/password/index", |
| | | "style": { |
| | | "navigationBarTitleText": "修改密码" |
| | | } |
| | | }, |
| | | { |
| | | "path": "browser/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图" |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "tabBar": { |
| | | "color": "#8c8c8c", |
| | | "selectedColor": "#1D6FE9", |
| | | "borderStyle": "black", |
| | | "backgroundColor": "#ffffff", |
| | | "list": [ |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/work/index", |
| | | "text": "工单" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/voiceCall/index", |
| | | "text": "通话" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_home1.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.png", |
| | | "pagePath": "pages/map/index", |
| | | "text": "地图" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_me.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.png", |
| | | "pagePath": "pages/user/index", |
| | | "text": "我的" |
| | | } |
| | | ] |
| | | }, |
| | | "globalStyle": { |
| | | "navigationBarTextStyle": "black", |
| | | "navigationBarTitleText": "uni-app", |
| | | "navigationBarBackgroundColor": "#F8F8F8", |
| | | "backgroundColor": "#F8F8F8" |
| | | } |
| | | { |
| | | "path": "pages/user/index", |
| | | "style": { |
| | | "navigationBarTitleText": "我的", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/login/index", |
| | | "style": { |
| | | "navigationBarTitleText": "登录页", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | | { |
| | | "root": "subPackages", |
| | | "pages": [ |
| | | { |
| | | "path": "404/index", |
| | | "style": { |
| | | "navigationBarTitleText": "404", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/index", |
| | | "style": { |
| | | "navigationBarTitleText": "工单详情" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/mapWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "工单位置" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/infos/index", |
| | | "style": { |
| | | "navigationBarTitleText": "个人资料" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/password/index", |
| | | "style": { |
| | | "navigationBarTitleText": "修改密码" |
| | | } |
| | | }, |
| | | { |
| | | "path": "browser/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图" |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "tabBar": { |
| | | "color": "#8c8c8c", |
| | | "selectedColor": "#1D6FE9", |
| | | "borderStyle": "black", |
| | | "backgroundColor": "#ffffff", |
| | | "list": [ |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/work/index", |
| | | "text": "工单管理" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/voiceCall/index", |
| | | "text": "语音通话" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_home1.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.png", |
| | | "pagePath": "pages/map/index", |
| | | "text": "地图" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_me.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.png", |
| | | "pagePath": "pages/user/index", |
| | | "text": "我的" |
| | | } |
| | | ] |
| | | }, |
| | | "globalStyle": { |
| | | "navigationBarTextStyle": "black", |
| | | "navigationBarTitleText": "uni-app", |
| | | "navigationBarBackgroundColor": "#F8F8F8", |
| | | "backgroundColor": "#F8F8F8" |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <view class="login-form-wrap"> |
| | | <image class="logo" :src="logoSvg" /> |
| | | <div class="title">掌控智飞</div> |
| | | <div class="title">低空经济服务一体化平台系统</div> |
| | | <div class="user-name"> |
| | | <image :src="usernameSvg" /> |
| | | <!-- <image :src="usernameSvg" /> --> |
| | | <input v-model="loginForm.username" placeholder="请输入用户名" /> |
| | | </div> |
| | | <div class="pass-word"> |
| | | <image :src="passwordSvg" /> |
| | | <!-- <image :src="passwordSvg" /> --> |
| | | <input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | placeholder="请输入密码" |
| | | /> |
| | | <image :src="showPasswordSvg" /> |
| | | </div> |
| | | <div class="remember-password"> |
| | | <label> |
| | |
| | | </checkbox-group> |
| | | 记住密码 |
| | | </label> |
| | | <div>忘记密码?</div> |
| | | </div> |
| | | |
| | | <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button> |
| | | <image class="lowerRightCorner" :src="droneSvg" /> |
| | | <view class="agreement"> |
| | | <label> |
| | | <checkbox :checked="agreed" @click="agreed = !agreed" /> |
| | | 同意《用户协议》与《隐私政策》 |
| | | </label> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { useUserStore } from "@/store/index.js"; |
| | | |
| | | import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router"; |
| | | import { onMounted } from "vue"; |
| | | import { ref } from "vue"; |
| | | |
| | | import logoSvg from "@/static/images/logo.svg"; |
| | | import showPasswordSvg from "@/static/images/show-password.svg"; |
| | | |
| | | const droneSvg = getAssetsImage("/images/login/droneSvg.svg"); |
| | | const usernameSvg = getAssetsImage("/images/login/username.svg"); |
| | | const passwordSvg = getAssetsImage("/images/login/password.svg"); |
| | | const logoSvg = getAssetsImage("/images/login/logo.svg"); |
| | | // const logoSvg = getAssetsImage("/images/login/logo.svg"); |
| | | |
| | | const agreed = ref(true); |
| | | |
| | | const userStore = useUserStore(); |
| | | const loginForm = ref({ |
| | |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | // md5(userInfo.password), |
| | | userInfo.password, |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data); |
| | | userStore.setUserInfo(res.data.data); |
| | | uni.reLaunch({ |
| | | url: "/pages/map/index", |
| | | url: "/pages/work/index", |
| | | }); |
| | | } catch (error) { |
| | | const errorMsg = |
| | | error.data?.error_description !== "Bad credentials" |
| | | ? error.data?.error_description |
| | | : "登录失败,请重试"; |
| | | error.data?.msg |
| | | ? error.data.msg |
| | | : (error.data?.error_description && error.data.error_description !== "Bad credentials") |
| | | ? error.data.error_description |
| | | : "登录失败,请重试"; |
| | | uni.showToast({ |
| | | title: errorMsg, |
| | | icon: "none", |
| | |
| | | .title { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-weight: 400; |
| | | font-size: 84rpx; |
| | | font-size: 52rpx; |
| | | line-height: 82rpx; |
| | | letter-spacing: 1px; |
| | | text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18); |
| | | text-align: center; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | color: #1452d3; |
| | | color: #161B2C; |
| | | text-align: center; |
| | | margin-bottom: 168rpx; |
| | | } |
| | | |
| | | .user-name{ |
| | | margin-bottom: 40rpx; |
| | | } |
| | | .user-name, |
| | | .pass-word { |
| | | display: flex; |
| | |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | | height: 118rpx; |
| | | border-bottom: 2rpx solid #e3e3e3; |
| | | height: 100rpx; |
| | | background: #F1F4F9; |
| | | border-radius: 8rpx 8rpx 8rpx 8rpx; |
| | | padding: 0 22rpx; |
| | | |
| | | image { |
| | | width: 40rpx; |
| | |
| | | |
| | | .remember-password { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | justify-content:space-between; |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | |
| | | } |
| | | } |
| | | |
| | | .wechat-login-btn { |
| | | z-index: 1; |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #07C160; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 30rpx; |
| | | |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | color: $u-tips-color; |
| | |
| | | color: $u-warning; |
| | | } |
| | | } |
| | | .agreement { |
| | | position: absolute; |
| | | bottom: 40rpx; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | text-align: center; |
| | | } |
| | | </style> |
| | |
| | | <u-avatar :src="user.avatar" size="70" /> |
| | | </view> |
| | | <view class="flex-1"> |
| | | <view class="userName">{{ userStore?.userInfo?.nick_name }}</view> |
| | | <view class="userName">{{user.nickName }}</view> |
| | | <view class="departs"> |
| | | <image |
| | | src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/mobile.svg" |
| | | src="@/static/images/user/department.svg" |
| | | alt="" |
| | | /> |
| | | <span>{{ user.deptName }}</span> |
| | | <span>{{ user?.sysDept?.deptName }}</span> |
| | | </view> |
| | | </view> |
| | | <view class="rightLogo"> |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 语音通话 |
| | | </view> |
| | | <div class="voiceCallContainer" :style="{ paddingTop: topMargin + 'px' }"> |
| | | <!-- 顶部搜索栏 --> |
| | | <div class="searchBar"> |
| | | <up-search placeholder="请输入关键字搜索" :animation="true" :show-action="false"></up-search> |
| | | </div> |
| | | |
| | | <!-- 联系人列表 --> |
| | | <div class="contactList"> |
| | | <div |
| | | class="contactItem" |
| | | v-for="(contact, index) in filteredContacts" |
| | | :key="index" |
| | | > |
| | | <div class="itemBox"> |
| | | <!-- 头像 --> |
| | | <div class="contactAvatar"> |
| | | <image :src="contact.avatar" mode="aspectFill" /> |
| | | </div> |
| | | |
| | | <!-- 联系人信息 --> |
| | | <div class="contactInfo"> |
| | | <div class="contactName">{{ contact.name }}</div> |
| | | <div class="contactDept">{{ contact.dept }}</div> |
| | | </div> |
| | | |
| | | <!-- 电话按钮 --> |
| | | <div class="callButton" @click="makeCall(contact)"> |
| | | <image src="@/static/images/voiceVal/phoneVal.svg" mode="aspectFit" /> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup></script> |
| | | <script setup> |
| | | import { getStatusBarHeight } from '@/utils/common'; |
| | | const topMargin = getStatusBarHeight() |
| | | |
| | | // 搜索关键字 |
| | | const searchKeyword = ref('') |
| | | |
| | | // 联系人数据 |
| | | const contacts = ref([ |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | { name: '张晓晓', dept: '吉州区应急部门', avatar: '/static/images/tabbar/icon_me.png' }, |
| | | ]) |
| | | |
| | | // 过滤后的联系人列表 |
| | | const filteredContacts = computed(() => { |
| | | if (!searchKeyword.value) { |
| | | return contacts.value |
| | | } |
| | | return contacts.value.filter(contact => { |
| | | return contact.name.includes(searchKeyword.value) || |
| | | contact.dept.includes(searchKeyword.value) |
| | | }) |
| | | }) |
| | | |
| | | // 拨打电话方法 |
| | | const makeCall = (contact) => { |
| | | console.log('拨打电话给', contact.name) |
| | | // 这里可以添加实际的拨打电话逻辑 |
| | | uni.showToast({ |
| | | title: `正在拨打${contact.name}的电话`, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | height: 100%; |
| | | .voiceCallContainer { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .searchBar { |
| | | padding: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | height: 108rpx; |
| | | } |
| | | |
| | | .contactList { |
| | | margin: 0 24rpx; |
| | | background: #fff; |
| | | border-radius: 12rpx ; |
| | | overflow-y: auto; |
| | | height: 0; |
| | | flex-grow: 1; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .contactItem { |
| | | display: flex; |
| | | align-items: center; |
| | | padding:0 24rpx; |
| | | |
| | | } |
| | | .itemBox { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width:100%; |
| | | height: 98rpx; |
| | | border-bottom: 1rpx solid #EBEBEB; |
| | | } |
| | | .contactAvatar { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | margin-right: 26rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .contactAvatar image { |
| | | width: 60rpx; |
| | | height: 60rpx; |
| | | } |
| | | |
| | | .contactInfo { |
| | | flex: 1; |
| | | display: flex; |
| | | justify-content: space-around; |
| | | align-items: center; |
| | | } |
| | | |
| | | .contactName { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | margin-bottom: 8rpx; |
| | | } |
| | | |
| | | .contactDept { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | } |
| | | |
| | | .callButton { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .callButton image { |
| | | width: 60rpx; |
| | | height: 60rpx; |
| | | |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 工单 |
| | | </view> |
| | | <div class="eventTickets" :style="{ paddingTop: topMargin + 'px' }"> |
| | | |
| | | <div class="searchTop"> |
| | | <up-search placeholder="请输入关键字搜索" :animation="true" v-model="listParams.keyword" :show-action="false"></up-search> |
| | | </div> |
| | | <div class="listBox"> |
| | | <div class="tabs-container"> |
| | | <up-tabs :list="tabList" @click="handleClick"></up-tabs> |
| | | </div> |
| | | |
| | | <div class="eventBox"> |
| | | <div class="eventItem" v-for="(item,index) in dataList" :key="index"> |
| | | <img :src="item.photo_url" alt="" @click="detailHandle(item)" /> |
| | | <div class="informationDisplay"> |
| | | <div class="itemTitle">{{item.event_name}}</div> |
| | | <div class="itemContent">{{formatDate(item.create_time) }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | import { useUserStore } from '@/store/index.js' |
| | | import {getList,getstatusCount} from '/src/api/work/index.js' |
| | | import dayjs from 'dayjs'; |
| | | import { getStatusBarHeight } from '@/utils/common'; |
| | | const userStore = useUserStore() |
| | | const userInfo = userStore.userInfo |
| | | const dataList = ref([]) |
| | | const currentTab=ref('all') |
| | | const tabList = ref([ |
| | | { |
| | | name: '全部工单', |
| | | key: 'all', |
| | | badge: { |
| | | value: 2 |
| | | }, |
| | | status: null |
| | | }, |
| | | { |
| | | name: '我的工单', |
| | | key: 'myTickets', |
| | | badge: { |
| | | value: 1 |
| | | } |
| | | }, |
| | | |
| | | |
| | | ]) |
| | | const formatDate = (dateString) => { |
| | | return dayjs(dateString).format('MM/DD HH:mm'); |
| | | }; |
| | | const listParams = ref({ |
| | | status: null, |
| | | current: 1, |
| | | size: 9999, |
| | | source: 1, |
| | | department:'', |
| | | keyword:'' |
| | | |
| | | }) |
| | | const getDataList = () => { |
| | | const params = { |
| | | current: 1, |
| | | size: 9999, |
| | | source: 1, |
| | | status:listParams.value.status, |
| | | event_name:listParams.value.keyword, |
| | | user_id:currentTab.value=== 'myTickets' ?userInfo.user_id : undefined |
| | | } |
| | | getList(params).then(res => { |
| | | |
| | | const response = res.data.data.records |
| | | dataList.value = response |
| | | }) |
| | | } |
| | | // const getstatusCountData=()=>{ |
| | | // getstatusCount().then(res=>{ |
| | | // const response = res.data.data |
| | | // const { statusCount, totalCount, userCount } = response |
| | | // tabList.value.forEach(tab=>{ |
| | | // |
| | | // if(tab.key === 'all'){ |
| | | // tab.badge.value = totalCount || 0 |
| | | // |
| | | // }else if(tab.key === 'myTickets'){ |
| | | // tab.badge.value = userCount || 0 |
| | | // }else{ |
| | | // tab.badge.value=statusCount[String(tab.status)] || 0 |
| | | // } |
| | | // }) |
| | | // |
| | | // }) |
| | | // } |
| | | |
| | | const handleClick = (item) => { |
| | | currentTab.value = item.key |
| | | listParams.value.status = item.status |
| | | getDataList() |
| | | } |
| | | const detailHandle = (val) => { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/index?eventNum=${val.event_num}`, |
| | | }) |
| | | } |
| | | const topMargin = getStatusBarHeight() |
| | | onShow(() => { |
| | | getDataList() |
| | | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | padding: 0 20rpx; |
| | | display: flex; |
| | | flex-direction: column; |
| | | height: 100%; |
| | | box-sizing: border-box; |
| | | .searchTop { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding-right: 24rpx; |
| | | width: 100%; |
| | | height: 108rpx; |
| | | } |
| | | :deep(){ |
| | | |
| | | .u-tabs__wrapper__nav__line{ |
| | | width: 80rpx !important; |
| | | background: #1D6FE9 !important; |
| | | } |
| | | .u-badge { |
| | | background-color: #1d6fe9 !important; |
| | | } |
| | | } |
| | | |
| | | |
| | | .tabs-container{ |
| | | display: flex; |
| | | justify-content: center; |
| | | height: 98rpx; |
| | | } |
| | | .listBox { |
| | | position: relative; |
| | | display: flex; |
| | | flex-direction: column; |
| | | flex: 1; |
| | | } |
| | | .eventBox { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20rpx; |
| | | padding: 20rpx 0; |
| | | overflow-y: auto; |
| | | height: 0; |
| | | flex-grow: 1; |
| | | align-content: flex-start; |
| | | |
| | | .eventItem { |
| | | width: calc(50% - 10rpx); |
| | | background-color: #fff; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | |
| | | img { |
| | | width: 341rpx; |
| | | height: 196rpx; |
| | | border-radius: 12rpx; |
| | | overflow: hidden; |
| | | } |
| | | .informationDisplay{ |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 10rpx 20rpx 10rpx 12rpx; |
| | | .itemTitle { |
| | | width: 144rpx; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 500; |
| | | font-size: 28rpx; |
| | | color: #000000; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .itemContent { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 24rpx; |
| | | color: rgba(0,0,0,0.5); |
| | | |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | import pagesJson from "@/pages.json" |
| | | |
| | | // 路径常量 |
| | | export const HOME_PATH = "/pages/map/index" |
| | | export const HOME_PATH = "/pages/work/index" |
| | | export const LOGIN_PATH = "/pages/login/index" |
| | | export const ERROR404_PATH = "/pages/common/404/index" |
| | | |
| New file |
| | |
| | | <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_77_1168)"> |
| | | <path id="Vector" d="M0.934694 12.1004C0.934694 12.597 1.36889 13 1.90319 13H3.79989C4.33419 13 4.76839 12.597 4.76839 12.1004C4.76839 11.6038 4.33419 11.2008 3.79989 11.2008H1.90319C1.36759 11.2008 0.934694 11.6038 0.934694 12.1004ZM1.86289 5.80579H3.79989C4.33419 5.80579 4.76839 5.40279 4.76839 4.90619C4.76839 4.40959 4.33419 4.00659 3.79989 4.00659H1.86289C1.32859 4.00659 0.894394 4.40959 0.894394 4.90619C0.894394 5.40279 1.32729 5.80579 1.86289 5.80579ZM4.76839 19.2946C4.76839 18.798 4.33419 18.395 3.79989 18.395H1.86289C1.32859 18.395 0.894394 18.798 0.894394 19.2946C0.894394 19.7912 1.32859 20.1942 1.86289 20.1942H3.79989C4.33419 20.1942 4.76839 19.7912 4.76839 19.2946Z" fill="#2EB28E"/> |
| | | <path id="Vector_2" d="M24.1371 1.36492L22.2001 1.30902C22.2001 0.812424 21.7659 0.409424 21.2316 0.409424H3.84021C3.30591 0.409424 2.87171 0.812424 2.87171 1.30902V3.05102H3.84021C3.84021 3.05102 5.76811 3.22002 5.76811 4.85022C5.76811 4.85022 5.78891 6.65202 3.79081 6.65202L2.87171 6.70402L2.89121 10.2452H3.79471C3.79471 10.2452 5.78761 10.2452 5.78761 12.1562C5.78761 12.1562 5.60171 13.8995 3.78561 13.8995H2.87431L2.85741 17.4394H3.82201C3.82201 17.4394 5.75511 17.4953 5.75511 19.2945C5.75511 19.2945 5.75121 21.1496 3.75441 21.1496L2.88211 21.0937L2.87041 22.8929C2.87041 22.8929 3.98061 25.5904 5.67451 25.5904H24.1969C24.1969 25.5904 25.1043 25.4214 25.1043 24.7467V2.26452C25.1056 2.26452 24.9249 1.36492 24.1371 1.36492ZM7.67391 6.70402H20.2644V13.8982H7.67391V6.70402ZM22.2001 23.7912H5.73691C5.73691 23.7912 4.73851 23.4818 4.73851 22.8643L21.2329 22.8552C21.7685 22.8552 22.2014 22.4522 22.2014 21.9556V2.12412L23.1998 2.43352V22.9488C23.1998 22.9488 23.2297 23.7912 22.2001 23.7912Z" fill="url(#paint0_linear_77_1168)"/> |
| | | <path id="Vector_3" d="M17.8425 8.50342H10.0945C9.8267 8.50342 9.6109 8.70492 9.6109 8.95322C9.6109 9.20152 9.828 9.40302 10.0945 9.40302H17.8425C18.1103 9.40302 18.3261 9.20152 18.3261 8.95322C18.3261 8.70492 18.1103 8.50342 17.8425 8.50342ZM17.8425 11.2009H10.0945C9.8267 11.2009 9.6109 11.4024 9.6109 11.6507C9.6109 11.899 9.828 12.1005 10.0945 12.1005H17.8425C18.1103 12.1005 18.3261 11.899 18.3261 11.6507C18.3261 11.4024 18.1103 11.2009 17.8425 11.2009Z" fill="#2EB28E"/> |
| | | </g> |
| | | <defs> |
| | | <linearGradient id="paint0_linear_77_1168" x1="13.9809" y1="0.409424" x2="13.9809" y2="25.5904" gradientUnits="userSpaceOnUse"> |
| | | <stop stop-color="#226BEA"/> |
| | | <stop offset="1" stop-color="#58AFF9"/> |
| | | </linearGradient> |
| | | <clipPath id="clip0_77_1168"> |
| | | <rect width="26" height="26" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_77_1180)"> |
| | | <path id="Vector" d="M21.1866 1H2.8134C2.33493 1 2 1.37879 2 1.80492V25.1951C2 25.6212 2.38277 26 2.8134 26H15.1579C14.2488 24.8636 13.6746 23.4432 13.6746 21.8333C13.6746 18.0928 16.7368 15.0625 20.5167 15.0625C21.0431 15.0625 21.5215 15.1098 22 15.2045V1.80492C22 1.37879 21.6651 1 21.1866 1ZM11.5215 14.3049H6.25837C5.82775 14.3049 5.49282 13.9735 5.49282 13.5473C5.49282 13.1212 5.82775 12.7898 6.25837 12.7898H11.5215C11.9522 12.7898 12.2871 13.1212 12.2871 13.5473C12.2871 13.9735 11.9043 14.3049 11.5215 14.3049ZM16.7368 9.09659H6.21053C5.7799 9.09659 5.44498 8.76515 5.44498 8.33902C5.44498 7.91288 5.7799 7.58144 6.21053 7.58144H16.7368C17.1675 7.58144 17.5024 7.91288 17.5024 8.33902C17.5024 8.76515 17.1675 9.09659 16.7368 9.09659Z" fill="url(#paint0_linear_77_1180)"/> |
| | | <g id="Frame_2" clip-path="url(#clip1_77_1180)"> |
| | | <path id="Vector_2" d="M19.6849 21.3826L19.9017 21.6248L20.2112 21.5251L22.6458 20.741L22.6448 20.74C22.6671 20.733 22.6926 20.734 22.7278 20.7585C22.7672 20.786 22.8199 20.8482 22.8441 20.9568C22.9001 21.2096 22.7536 21.3612 22.6927 21.3806H22.6907L20.261 22.1707L18.2718 22.8113L15.8362 23.5955L15.513 23.698L15.3499 23.3591L14.9407 22.5085L15.2855 22.8328L15.5003 23.0349L15.7806 22.9451L18.0579 22.2156L18.6048 22.0408L18.3558 21.5232L16.7073 18.0935L16.7376 18.0847L19.6849 21.3826Z" fill="#2EB28E" stroke="#2EB28E"/> |
| | | </g> |
| | | </g> |
| | | <defs> |
| | | <linearGradient id="paint0_linear_77_1180" x1="12" y1="1" x2="12" y2="26" gradientUnits="userSpaceOnUse"> |
| | | <stop stop-color="#1E66E9"/> |
| | | <stop offset="1" stop-color="#5BB3FA"/> |
| | | </linearGradient> |
| | | <clipPath id="clip0_77_1180"> |
| | | <rect width="26" height="26" fill="white"/> |
| | | </clipPath> |
| | | <clipPath id="clip1_77_1180"> |
| | | <rect width="9.28571" height="11.1429" fill="white" transform="translate(14.0648 15.7952)"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_77_1162)"> |
| | | <path id="Vector" d="M2.59999 1.30005H22.1C22.4448 1.30005 22.7754 1.43701 23.0192 1.68081C23.263 1.92461 23.4 2.25527 23.4 2.60005V24.7C23.3998 24.9126 23.3475 25.1219 23.2477 25.3095C23.1479 25.4971 23.0036 25.6575 22.8274 25.7764C22.6513 25.8953 22.4486 25.9692 22.2373 25.9917C22.0259 26.0141 21.8123 25.9844 21.6151 25.9051L12.35 22.1754L3.08489 25.9064C2.88758 25.9858 2.67383 26.0155 2.46237 25.993C2.25091 25.9705 2.0482 25.8964 1.87201 25.7773C1.69583 25.6582 1.55154 25.4978 1.45181 25.3099C1.35208 25.1221 1.29995 24.9127 1.29999 24.7V2.60005C1.29999 2.25527 1.43695 1.92461 1.68075 1.68081C1.92455 1.43701 2.25521 1.30005 2.59999 1.30005ZM12.35 16.601L15.7885 18.4119L15.132 14.5769L17.914 11.8599L14.0699 11.3009L12.35 7.81175L10.6301 11.3009L6.78599 11.8599L9.56799 14.5769L8.91149 18.4119L12.35 16.601ZM1.29999 3.90395V5.20655H23.4V3.90395H1.29999Z" fill="url(#paint0_linear_77_1162)"/> |
| | | <path id="Star 1" d="M12.3 10L13.3327 12.0786L15.6287 12.4184L13.971 14.0429L14.3572 16.3316L12.3 15.257L10.2427 16.3316L10.629 14.0429L8.97129 12.4184L11.2672 12.0786L12.3 10Z" fill="#2EB28E"/> |
| | | </g> |
| | | <defs> |
| | | <linearGradient id="paint0_linear_77_1162" x1="12.35" y1="1.30005" x2="12.35" y2="26.0003" gradientUnits="userSpaceOnUse"> |
| | | <stop stop-color="#256DE2"/> |
| | | <stop offset="1" stop-color="#56ACF9"/> |
| | | </linearGradient> |
| | | <clipPath id="clip0_77_1162"> |
| | | <rect width="26" height="26" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="67" height="67" viewBox="0 0 67 67" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321317860"> |
| | | <path id="Rectangle 346240814" d="M0 16.2424C0 7.27198 7.27198 0 16.2424 0H50.7576C59.728 0 67 7.27198 67 16.2424V50.7576C67 59.728 59.728 67 50.7576 67H16.2424C7.27198 67 0 59.728 0 50.7576V16.2424Z" fill="#477EFF"/> |
| | | <path id="Subtract" d="M55.5284 21.8262C51.7386 23.112 44.1583 27.1857 44.1583 33.1953C44.1584 39.2049 51.7386 43.5495 55.5284 44.9707L49.8439 50.25C48.2197 47.0693 42.697 40.7072 33.6017 40.707C24.506 40.707 19.1182 47.0692 17.5616 50.25L12.2833 44.9707C16.0732 43.2111 23.5719 38.3928 23.2472 33.1953C22.9224 27.9979 15.8025 23.4505 12.2833 21.8262L17.5616 16.75C19.4566 19.8631 24.2624 26.0889 33.6017 26.0889C42.9407 26.0887 48.2874 19.863 49.8439 16.75L55.5284 21.8262ZM33.5636 29.0342C26.8109 29.0342 23.9063 32.4504 23.298 34.1582C24.4389 35.9318 27.8606 39.0839 33.5636 39.084C39.9511 39.084 43.1198 35.8004 44.1085 34.1582C43.272 32.4504 40.3164 29.0342 33.5636 29.0342Z" fill="white"/> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="22" height="10" viewBox="0 0 22 10" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1142814567"> |
| | | <path id="Vector" d="M0.578552 0C0.945931 0.705736 1.50259 1.36042 2.21238 1.94212C4.20244 3.57313 7.39628 4.63043 10.997 4.63043C14.5978 4.63043 17.7916 3.57313 19.7816 1.94212C20.4914 1.36042 21.0481 0.705736 21.4155 0" stroke="#1D2129" stroke-width="2"/> |
| | | <path id="Vector_2" d="M13.8779 4.63086L15.0763 9.10351" stroke="#1D2129" stroke-width="2"/> |
| | | <path id="Vector_3" d="M18.7256 3.09961L21.9998 6.37379" stroke="#1D2129" stroke-width="2"/> |
| | | <path id="Vector_4" d="M0 6.37385L3.27421 3.09961" stroke="#1D2129" stroke-width="2"/> |
| | | <path id="Vector_5" d="M6.90381 9.10357L8.10222 4.63086" stroke="#1D2129" stroke-width="2"/> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_121_1431)"> |
| | | <path id="Vector" d="M1.24417 9.08086H2.29417V7.07383C2.29417 6.88789 2.44456 6.7375 2.63049 6.7375V6.72657H6.6637V4.86582H5.39358C5.17893 4.86582 5.00393 4.69082 5.00393 4.47617V1.70625C5.00393 1.4916 5.17893 1.3166 5.39358 1.3166H8.62561C8.84026 1.3166 9.01526 1.4916 9.01526 1.70625V4.47754C9.01526 4.69219 8.84026 4.86719 8.62561 4.86719H7.35549V6.7293H11.3887V6.74024C11.5746 6.74024 11.725 6.89063 11.725 7.07657V9.08223H12.775C12.9897 9.08223 13.1647 9.25723 13.1647 9.47188V12.2432C13.1647 12.4578 12.9897 12.6328 12.775 12.6328H10.0037C9.78909 12.6328 9.61409 12.4578 9.61409 12.2432V9.47051C9.61409 9.25586 9.78909 9.08086 10.0037 9.08086H11.0537V7.4211H7.34456V9.08086H8.39456C8.6092 9.08086 8.7842 9.25586 8.7842 9.47051V12.2418C8.7842 12.4564 8.6092 12.6314 8.39456 12.6314H5.62327C5.40862 12.6314 5.23362 12.4564 5.23362 12.2418V9.47051C5.23362 9.25586 5.40862 9.08086 5.62327 9.08086H6.67327V7.4211H2.96409V9.08086H4.01409C4.22873 9.08086 4.40374 9.25586 4.40374 9.47051V12.2418C4.40374 12.4564 4.22873 12.6314 4.01409 12.6314H1.24417C1.02952 12.6314 0.854517 12.4564 0.854517 12.2418V9.47051C0.854517 9.2545 1.02815 9.08086 1.24417 9.08086ZM8.23596 2.0959H5.78186V4.08789H8.23596V2.0959ZM10.3934 11.8508H12.3854V9.86016H10.3934V11.8508ZM6.01292 11.8508H8.00491V9.86016H6.01292V11.8508ZM1.63381 11.8508H3.62444V9.86016H1.63245V11.8508H1.63381Z" fill="#353637"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_121_1431"> |
| | | <rect width="14" height="14" fill="white" transform="matrix(-1 0 0 1 14 0)"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321318721"> |
| | | <g id="Group 1321318693"> |
| | | <g id="Group 1321318692"> |
| | | <circle id="Ellipse" cx="15" cy="15" r="15" fill="#1D6FE9"/> |
| | | </g> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M20.0291 16.6168C18.9934 16.6168 18.1094 17.2659 17.7614 18.1794C17.7604 18.1789 17.7623 18.1798 17.7614 18.1794C17.758 18.1892 17.7523 18.198 17.7452 18.2065C17.7218 18.2344 17.6825 18.2444 17.6496 18.2343C17.6496 18.2346 17.6497 18.234 17.6496 18.2343C15.3886 17.4001 13.5955 15.6012 12.7693 13.3363C12.767 13.3285 12.7654 13.3205 12.7654 13.3121C12.7654 13.2756 12.7873 13.2439 12.819 13.2305C12.8189 13.2304 12.8191 13.2307 12.819 13.2305C13.7405 12.8866 14.3969 11.9987 14.3969 10.9572C14.3969 9.61739 13.3107 8.53125 11.9709 8.53125C10.6311 8.53125 9.54492 9.61739 9.54492 10.9572C9.54492 10.9657 9.54516 10.974 9.54523 10.9825C9.78252 16.6675 14.3462 21.2315 20.0312 21.4688C21.3701 21.4676 22.455 20.3819 22.455 19.0428C22.455 17.703 21.3689 16.6168 20.0291 16.6168Z" fill="white"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_77_1174)"> |
| | | <path id="Vector" d="M23.2143 4.30487V4.86201C23.1581 4.98582 23.1019 5.04773 23.0457 5.17154C22.8772 5.35725 22.6524 5.41915 22.4277 5.41915H6.47043C5.96474 5.41915 5.57143 4.98582 5.57143 4.49058C5.57143 4.24296 5.6838 3.99534 5.85236 3.80963C6.02093 3.62392 6.24568 3.56201 6.47043 3.56201H22.3715C22.7648 3.56201 23.0457 3.80963 23.2143 4.11915V4.30487Z" fill="url(#paint0_linear_77_1174)"/> |
| | | <path id="Vector_2" d="M23.2143 2.14918V1.23381V1.06218C23.2143 0.890544 23.0457 0.776123 22.8771 0.776123H6.18477C3.88045 0.776123 1.96955 2.49244 1.85714 4.60923V21.3147C2.13815 23.3171 3.93665 24.919 6.12857 24.919H22.8209C22.9895 24.919 23.1581 24.7473 23.1581 24.5757V7.64139C23.1581 7.41255 22.9895 7.24092 22.7647 7.29813H13.3788V12.9048C13.3788 13.3052 13.2101 13.7057 12.8729 13.9346C12.7043 14.049 12.4795 14.1062 12.2547 14.1062C12.0861 14.1062 11.9175 14.049 11.8051 13.9918L9.27594 12.6759L6.803 13.9346C6.46579 14.1062 6.07236 14.1062 5.73515 13.8773C5.45413 13.6485 5.22932 13.248 5.22932 12.8476V7.46976C5.22932 7.35534 5.22932 7.24092 5.28552 7.1265C4.33007 6.78323 3.65564 5.92507 3.65564 4.89528C3.65564 3.57944 4.7797 2.49244 6.18477 2.49244H22.7647C22.9895 2.49244 23.2143 2.32081 23.2143 2.14918Z" fill="url(#paint1_linear_77_1174)"/> |
| | | <path id="Vector_3" d="M7.06031 11.5785V7.91968H11.6485H11.7032V11.634L11.6485 11.6055L11.6485 11.634L9.73678 10.6361C9.63366 10.5838 9.48187 10.5315 9.32735 10.5258C9.17813 10.5315 9.07213 10.5838 8.91745 10.6361L7.06031 11.5785Z" fill="#2EB28E"/> |
| | | </g> |
| | | <defs> |
| | | <linearGradient id="paint0_linear_77_1174" x1="14.3929" y1="3.56201" x2="14.3929" y2="5.41915" gradientUnits="userSpaceOnUse"> |
| | | <stop stop-color="#1E66E9"/> |
| | | <stop offset="1" stop-color="#5AB3FA"/> |
| | | </linearGradient> |
| | | <linearGradient id="paint1_linear_77_1174" x1="12.5357" y1="0.776123" x2="12.5357" y2="24.919" gradientUnits="userSpaceOnUse"> |
| | | <stop stop-color="#1E66E9"/> |
| | | <stop offset="1" stop-color="#5AB3FA"/> |
| | | </linearGradient> |
| | | <clipPath id="clip0_77_1174"> |
| | | <rect width="26" height="26" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <div class="avatarBox"> |
| | | <u-avatar @click="uploadAvatar" :src="userInfo.avatar" size="114" mode="aspectFill" /> |
| | | <!-- @click="uploadAvatar" --> |
| | | <u-avatar :src="userInfo.avatar" size="114" mode="aspectFill" /> |
| | | </div> |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">姓名</div> |
| | | <div>{{userInfo.realName}}</div> |
| | | </div> |
| | | <div class="rowTitle">姓名</div> |
| | | <u-input input-align="right" v-model="userInfo.nickName" placeholder="请输入姓名" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">所属单位</div> |
| | | <div>{{userInfo.deptName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">手机号</div> |
| | | <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | | class="input-item" /> |
| | | <div>{{userInfo.phone}}</div> |
| | | <!-- <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | | class="input-item" /> --> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">邮箱</div> |
| | | <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> |
| | | <div>{{userInfo.email}}</div> |
| | | <!-- <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> --> |
| | | </div> |
| | | </div> |
| | | </view> |
| | |
| | | getEnvObj, |
| | | getWebViewUrl |
| | | } from "@/utils/index.js"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | const userInfo = ref({ |
| | | id: '', |
| | | import { getUserInfo, updateInfo, updatePassword } from '@/api/user/index.js'; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | const userInfo = ref({ |
| | | userId: '', |
| | | avatar: '', |
| | | realName: '', |
| | | name: '', |
| | | nickName: '', |
| | | phone: '', |
| | | email: '', |
| | | deptName: '', |
| | |
| | | getUserInfo().then(res => { |
| | | const user = res.data.data; |
| | | userInfo.value = { |
| | | id: user.id, |
| | | userId: user.userId, |
| | | avatar: user.avatar, |
| | | name: user.name, |
| | | realName: user.realName, |
| | | phone: user.phone, |
| | | email: user.email, |
| | | deptName: user.deptName, |
| | | nickName: user.nickName, |
| | | phone: user.sysDept.phone, |
| | | email: user.sysDept.email, |
| | | deptName: user.sysDept.deptName, |
| | | }; |
| | | |
| | | }); |
| | |
| | | const pathWithoutProtocol = filePath.replace(/^file:\/\//, ''); |
| | | fileName = pathWithoutProtocol.split('/').pop() || 'unknown.png'; |
| | | } |
| | | |
| | | |
| | | // 显示加载中 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | filePath: filePath, |
| | | filePath: filePath, |
| | | formData: { |
| | | fileName: fileName, |
| | | fileName: fileName, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | |
| | | } |
| | | const submit = () => { |
| | | if (!validatePhone() || !validateEmail()) return |
| | | userInfo.value.name = userInfo.value.realName; |
| | | updateInfo(userInfo.value).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | |
| | | } |
| | | |
| | | }); |
| | | |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | getUserInfoData() |
| | |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | ::v-deep .u-input { |
| | | :deep(.u-input) { |
| | | border: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | ::v-deep .u-input__input { |
| | | :deep(.u-input__input) { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | |
| | | width: 276rpx !important; |
| | | height: 76rpx !important; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | <!-- 工单详情 - 包含待审核、待处理、处理中、已完成 --> |
| | | <!-- 工单详情 --> |
| | | <template> |
| | | <div class="workDetailContainer"> |
| | | <WebViewPlus |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | @webMessage="onPostMessage" |
| | | /> |
| | | <div class="detailTop"> |
| | | <div class="image-container"> |
| | | <u-swiper |
| | | class="detailImage" |
| | | :list="getImageList" |
| | | mode="round" |
| | | indicator |
| | | indicatorMode="dot" |
| | | indicatorActiveColor="#4C85FF" |
| | | indicatorInactiveColor="#fff" |
| | | indicatorPosition="center" |
| | | height="410rpx" |
| | | @click="previewImage" |
| | | ></u-swiper> |
| | | <!-- <div class="detailTitle">--> |
| | | <!-- <div class="titleText">--> |
| | | <!-- <div class="itemName">{{workDetailData.event_name}}</div>--> |
| | | <!-- <div class="itemTime">{{formatDate(workDetailData.create_time)}}</div>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 工单内容 --> |
| | | <div class="worderContainer"> |
| | | <div class="workOrderContent"> |
| | | <div class="workOrderTitle">工单内容</div> |
| | | <div class="workOrderContainer"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">工单编号</div> |
| | | <div>{{workDetailData.event_num}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">工单处置人</div> |
| | | <div>{{workDetailData.event_num?.slice(0, 2) === 'AI' ? 'AI 小飞':workDetailData.creator}} |
| | | </div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">处置部门</div> |
| | | <div>{{ workDetailData.dept_name }}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">拍摄时间</div> |
| | | <div>{{ workDetailData.create_time }}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">分发人员</div> |
| | | <div>{{ workDetailData.remark }}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">分发部门</div> |
| | | <div>{{ workDetailData.remark }}</div> |
| | | </div> |
| | | |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">分发时间</div> |
| | | <div>{{ workDetailData.create_time }}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">工单位置</div> |
| | | <div class="rowAddress" @click="jumpMap(workDetailData)">{{ workDetailData.address }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | <!-- 操作按钮 --> |
| | | <div class="actionButton"> |
| | | <div class="btngroups" > |
| | | <up-button type="primary" color="#AEAEAE" text="退回"></up-button> |
| | | <up-button type="primary" color="#1D6FE9" text="确认"></up-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | const userStore = useUserStore(); |
| | | const userInfo = userStore.userInfo; |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = ref(""); |
| | | onLoad((options) => { |
| | | const eventNum = options.eventNum; |
| | | viewUrl.value = getWebViewUrl("/workDetail", { |
| | | eventNum: eventNum, |
| | | totalNum: options.totalNum, |
| | | keyword: options.keyword, |
| | | aiType: options.aiType, |
| | | wLJobInfoId: options.wLJobInfoId, |
| | | status: options.status, |
| | | current: options.current, |
| | | }); |
| | | // import { getShowImg, getSmallImg } from '@/utils/util' |
| | | import {getList,flowEvent} from '/src/api/work/index.js' |
| | | import dayjs from 'dayjs' |
| | | |
| | | const formatDate = dateString => { |
| | | return dayjs(dateString).format('MM/DD HH:mm') |
| | | } |
| | | const eventNum = ref(''); |
| | | // 工单内容 |
| | | const workDetailData = ref({}) |
| | | onLoad(async (options) => { |
| | | eventNum.value = options.eventNum; |
| | | await getDataList(eventNum.value); |
| | | |
| | | }); |
| | | |
| | | function onPostMessage(data) { |
| | | if (data.type === "workback") { |
| | | // #ifdef MP-WEIXIN |
| | | if ("fun" in data && data.fun === "add") { |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | uni.switchTab({ |
| | | url: `/pages/work/index?addLog=111`, |
| | | // url: '/pages/work/index' |
| | | }); |
| | | // #endif |
| | | } else if (data.type === "jumpMapNav") { |
| | | // #ifndef MP-WEIXIN |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`, |
| | | }); |
| | | // #endif |
| | | const getDataList = async (val) => { |
| | | const params = { |
| | | current: 1, |
| | | size: 9999, |
| | | source: 1, |
| | | event_name: val |
| | | } |
| | | const res = await getList(params); |
| | | const response = res.data.data.records; |
| | | workDetailData.value = response[0]; |
| | | |
| | | console.log('详情',response); |
| | | } |
| | | // 图片预览 |
| | | |
| | | const previewImage = (index) => { |
| | | if (getImageList.value.length === 0) return; |
| | | const currentIndex = typeof index === 'number' ? index : 0; |
| | | uni.previewImage({ |
| | | urls: getImageList.value, |
| | | current: currentIndex |
| | | }); |
| | | }; |
| | | const getImageList =computed(()=>{ |
| | | const imageArr = [] |
| | | const detail = workDetailData.value |
| | | if (detail.photo_url) { |
| | | const smallUrl = detail.photo_url |
| | | imageArr.push(smallUrl) |
| | | } |
| | | if (detail.update_photo_url) { |
| | | const smallUrl =detail.update_photo_url |
| | | imageArr.push(smallUrl) |
| | | } |
| | | return imageArr |
| | | }) |
| | | // 跳转地图 |
| | | const jumpMap = item => { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?eventNum=${item.event_num}`, |
| | | }) |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .workDetailContainer { |
| | | width: 100%; |
| | | height: 100%; |
| | | background-size: cover; |
| | | .detailTop { |
| | | .image-container { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 410rpx; |
| | | |
| | | .detailImage { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: block; |
| | | object-fit: cover; |
| | | } |
| | | // 轮播图容器 |
| | | :deep(.u-swiper) { |
| | | // 指示器容器 - 修改为居中对齐 |
| | | .u-swiper__indicator { |
| | | position: absolute; |
| | | left: 50%; |
| | | transform: translateX(-50%); |
| | | bottom: 20rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | z-index: 10; |
| | | |
| | | } |
| | | .u-swiper-indicator__wrapper__dot--active{ |
| | | width: 5px !important; |
| | | } |
| | | } |
| | | .detailTitle { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 0; |
| | | width: 100%; |
| | | height: 60rpx; |
| | | line-height: 60rpx; |
| | | background: rgba(7, 7, 7, 0.4); |
| | | |
| | | } |
| | | |
| | | .titleText { |
| | | display: flex; |
| | | width: 100%; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | color: #fff; |
| | | |
| | | .itemName, .itemTime { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: #FFFFFF; |
| | | } |
| | | .itemName { |
| | | padding-left: 20rpx; |
| | | } |
| | | .itemTime{ |
| | | padding-right: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .worderContainer { |
| | | padding: 0 24rpx; |
| | | padding-bottom: 4rpx; |
| | | background: #f6f6f6; |
| | | margin-top: 20rpx; |
| | | } |
| | | .workOrderContent { |
| | | margin-top: 30epx; |
| | | background-color: #fff; |
| | | border-radius: 12rpx; |
| | | padding: 20rpx; |
| | | margin-bottom: 34rpx; |
| | | .workOrderTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: bold; |
| | | font-size: 32rpx; |
| | | color: #222324; |
| | | } |
| | | .workOrderContainer { |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | min-height: 96rpx; |
| | | border-bottom: 1px solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | |
| | | } |
| | | .rowAddress { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: #1D6FE9; |
| | | //white-space: nowrap; |
| | | ///* 禁止换行 */ |
| | | //overflow: hidden; |
| | | //text-overflow: ellipsis; |
| | | // max-width: 74%; |
| | | padding-top: 1px; |
| | | padding-left: 5px; |
| | | padding-right: 2px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .actionButton { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 61px; |
| | | |
| | | border-radius: 6px 6px 6px 6px; |
| | | |
| | | .btngroups { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | :deep(.u-button){ |
| | | width: 276rpx !important; |
| | | height: 100rpx !important; |
| | | &:last-child { |
| | | margin-left: 30rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-10-22 14:59:10 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-19 14:52:54 |
| | | * @FilePath : \src\subPackages\workDetail\mapWork\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-10-22 14:59:10 |
| | | --> |
| | | |
| | | <!-- 地图展示 --> |
| | | <template> |
| | | <WebViewPlus |
| | |
| | | const viewUrl = ref(""); |
| | | |
| | | onLoad((options) => { |
| | | const currentItem = options.currentItem; |
| | | const currentItem = options.eventNum; |
| | | viewUrl.value = getWebViewUrl("/mapWork", { currentItem: currentItem }); |
| | | }); |
| | | function onPostMessage(data) { |
| | |
| | | // 假设有token值需要在头部需要携带 |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | if (accessToken) { |
| | | config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | // config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | config.header['authorization'] = accessToken; |
| | | } |
| | | if (detail?.areaCode) { |
| | | config.header['areaCode'] = detail.areaCode |
| | | } |
| | | // if (detail?.areaCode) { |
| | | // config.header['areaCode'] = detail.areaCode |
| | | // } |
| | | // 安全请求header |
| | | config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // 客户端认证参数 |
| | | config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | // config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | return config |
| | | }, config => { // 可使用async await 做异步操作 |
| | | return Promise.reject(config) |
| | |
| | | // 用户登录接口 |
| | | export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | url: '/auth/login', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': tenantId, |
| | |
| | | 'Captcha-Key': key, |
| | | 'Captcha-Code': code, |
| | | }, |
| | | params: { |
| | | data: { |
| | | tenantId, |
| | | username, |
| | | password, |
| | | checkCode:'', |
| | | mobile: false, |
| | | grant_type: 'password', |
| | | scope: 'all', |
| | | type, |
| | |
| | | }); |
| | | }; |
| | | |
| | | // 微信登录接口 |
| | | export const loginByWechat = (code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': '000000', |
| | | }, |
| | | params: { |
| | | tenantId: '000000', |
| | | code, |
| | | grant_type: 'wechat', |
| | | scope: 'all', |
| | | type: 'wechat', |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 发送通话信息 |
| | | export const sendVoiceCallApi = (data) => { |
| | | return request({ |
| | |
| | | // 开发环境这里改为自己的 |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | // VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | VITE_API_BASE_URL: 'http://218.202.104.82:8200', |
| | | // VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | |
| | |
| | | </div> |
| | | |
| | | <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button> |
| | | <image class="lowerRightCorner" :src="droneSvg" /> |
| | | <button class="wechat-login-btn" @tap="wechatLogin">微信登录</button> |
| | | |
| | | <view class="agreement"> |
| | | <label> |
| | | <checkbox :checked="agreed" @click="agreed = !agreed" /> |
| | | 同意《用户协议》与《隐私政策》 |
| | | </label> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | import { useUserStore } from "@/store/index.js"; |
| | | |
| | | import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router"; |
| | | import { onMounted } from "vue"; |
| | | import { ref } from "vue"; |
| | | |
| | | import logoSvg from "@/static/images/logo.svg"; |
| | | import showPasswordSvg from "@/static/images/show-password.svg"; |
| | |
| | | const usernameSvg = getAssetsImage("/images/login/username.svg"); |
| | | const passwordSvg = getAssetsImage("/images/login/password.svg"); |
| | | // const logoSvg = getAssetsImage("/images/login/logo.svg"); |
| | | |
| | | const agreed = ref(true); |
| | | |
| | | const userStore = useUserStore(); |
| | | const loginForm = ref({ |
| | |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | // md5(userInfo.password), |
| | | userInfo.password, |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data); |
| | | userStore.setUserInfo(res.data.data); |
| | | uni.reLaunch({ |
| | | url: "/pages/map/index", |
| | | url: "/pages/page/index", |
| | | }); |
| | | } catch (error) { |
| | | const errorMsg = |
| | |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 核心登录函数 |
| | | const wechatLogin = async () => { |
| | | // 1. 协议检查 |
| | | if (!agreed.value) { |
| | | uni.showToast({ title: '请先同意协议', icon: 'none' }); |
| | | return; |
| | | } |
| | | |
| | | // loading.value = true; |
| | | |
| | | try { |
| | | // 2. 获取登录凭证 (code) |
| | | const loginRes = await uni.login({ |
| | | provider: 'weixin', |
| | | timeout: 10000 |
| | | }); |
| | | |
| | | if (!loginRes.code) { |
| | | throw new Error('获取登录码失败'); |
| | | } |
| | | console.log('获取到code:', loginRes.code); |
| | | |
| | | // 3. 获取用户信息 (需要用户授权弹窗) |
| | | const userProfileRes = await uni.getUserProfile({ |
| | | desc: '用于完善您的会员信息', // 声明用途,会展示给用户 |
| | | lang: 'zh_CN' |
| | | }); |
| | | |
| | | console.log('用户信息:', userProfileRes.userInfo); |
| | | |
| | | // 4. 调用后端登录接口 |
| | | const serverRes = await uni.request({ |
| | | // url: 'https://你的域名.com/api/wx-login', // 替换为你的真实接口 |
| | | // method: 'POST', |
| | | // data: { |
| | | // code: loginRes.code, |
| | | // rawData: userProfileRes.rawData, |
| | | // signature: userProfileRes.signature, |
| | | // encryptedData: userProfileRes.encryptedData, |
| | | // iv: userProfileRes.iv, |
| | | // userInfo: userProfileRes.userInfo // 注意:userInfo 仅为昵称头像等非敏感信息 |
| | | // }, |
| | | // header: { 'Content-Type': 'application/json' } |
| | | }); |
| | | |
| | | // 5. 处理登录结果 |
| | | const { data } = serverRes; |
| | | if (data.success && data.token) { |
| | | // 保存登录状态 |
| | | uni.setStorageSync('token', data.token); |
| | | uni.setStorageSync('userInfo', data.userInfo || userProfileRes.userInfo); |
| | | |
| | | uni.showToast({ title: '登录成功', icon: 'success' }); |
| | | |
| | | // 登录成功后的跳转逻辑 |
| | | const pages = getCurrentPages(); |
| | | if (pages.length > 1) { |
| | | uni.navigateBack(); |
| | | } else { |
| | | uni.switchTab({ url: '/pages/page/index' }); // 跳转到首页 |
| | | } |
| | | } else { |
| | | throw new Error(data.message || '登录失败'); |
| | | } |
| | | |
| | | } catch (error) { |
| | | console.error('登录全过程失败:', error); |
| | | uni.showToast({ |
| | | title: error.errMsg || error.message || '登录失败', |
| | | icon: 'none' |
| | | }); |
| | | } finally { |
| | | // loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // 从本地存储加载记住的密码 |
| | | onMounted(() => { |
| | |
| | | } |
| | | } |
| | | |
| | | .wechat-login-btn { |
| | | z-index: 1; |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #07C160; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 30rpx; |
| | | |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | color: $u-tips-color; |
| | |
| | | <text class="grid-text">{{baseListItem.title}}</text> |
| | | </u-grid-item> |
| | | </u-grid> |
| | | <u-tabs :list="list3" class="tabs"> |
| | | <u-tabs :list="tabs" class="tabs"> |
| | | <template #right> |
| | | <view |
| | | style="padding-left: 4px;" |
| | |
| | | </view> |
| | | </template> |
| | | </u-tabs> |
| | | <view class="card" v-for="(item,index) in list4" :key="index"> |
| | | <view class="card" v-for="(item,index) in announcementList" :key="index"> |
| | | <view class="left"> |
| | | <u-image :src="lbPng" :width="20" :height="20"></u-image> |
| | | </view> |
| | | <view class="right"> |
| | | <view class="c-top">{{ item.title }}</view> |
| | | <view class="c-middle">{{ item.content }}</view> |
| | | <view class="c-top">{{ item.airspaceName }}</view> |
| | | <view class="c-middle">{{ item.remarks || '暂无' }}</view> |
| | | <view class="c-bottom"> |
| | | <view>{{ item.time }}</view> |
| | | <view>{{ item.num }}</view> |
| | | <view>{{ item.like }}</view> |
| | | <view>{{ item.createTime }}</view> |
| | | <view>{{ item.num || 0 }}</view> |
| | | <view>{{ item.like || 0 }}</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { reactive, ref } from 'vue' |
| | | import { onMounted, reactive, ref } from 'vue' |
| | | import lbPng from '@/static/images/lb.png' |
| | | import kyxxPng from '@/static/images/kyxx.svg' |
| | | import fxsqPng from '@/static/images/fxsq.svg' |
| | | import flfgPng from '@/static/images/flfg.svg' |
| | | import zczdPng from '@/static/images/zczd.svg' |
| | | const lbList = reactive([]); |
| | | import { sysNoticePageInfoApi, flightAirspacePageInfoApi } from '@/api/index' |
| | | const lbList = reactive([]); |
| | | // lbPng 轮播图 5次 |
| | | for (let i = 0; i < 5; i++) { |
| | | lbList.push({ |
| | |
| | | if (args.length >= 2) { |
| | | const [item, index] = args; |
| | | console.log('点击了轮播图第', index + 1, '张', item); |
| | | // 轮播图点击跳转,使用switchTab因为目标页面是tabBar页面 |
| | | uni.switchTab({ |
| | | url: item.link, |
| | | }) |
| | | } |
| | | // 处理网格组件点击事件 |
| | | else if (args.length === 1 && typeof args[0] === 'object') { |
| | |
| | | } |
| | | } |
| | | |
| | | const baseList = ref([ |
| | | { |
| | | src: kyxxPng, |
| | | title: '空域信息' |
| | | }, |
| | | { |
| | | src: fxsqPng, |
| | | title: '飞行申请' |
| | | }, |
| | | { |
| | | src: flfgPng, |
| | | title: '法律法规' |
| | | }, |
| | | { |
| | | src: zczdPng, |
| | | title: '政策制度' |
| | | const baseList = ref([ |
| | | { |
| | | src: kyxxPng, |
| | | title: '空域信息' |
| | | }, |
| | | ]); |
| | | |
| | | const list3 = reactive([ |
| | | { name: '空域信息' }, |
| | | { name: '法律法规' }, |
| | | { name: '政策制度' }, |
| | | ]); |
| | | |
| | | const list4 = reactive([ |
| | | { title: '关于征求', content: '关于征求', time: '2025-10-23', num: '1660', like: '126' }, |
| | | { title: '解决燃气', content: '解决燃气', time: '2025-10-23', num: '126', like: '126' }, |
| | | { |
| | | src: fxsqPng, |
| | | title: '飞行申请' |
| | | }, |
| | | { |
| | | src: flfgPng, |
| | | title: '法律法规' |
| | | }, |
| | | { |
| | | src: zczdPng, |
| | | title: '政策制度' |
| | | }, |
| | | ]); |
| | | |
| | | const tabs = ref([ |
| | | { name: '空域信息' }, |
| | | { name: '法律法规' }, |
| | | { name: '政策制度' }, |
| | | ]); |
| | | |
| | | const announcementList = ref([]); |
| | | function gridClick(index) { |
| | | if (index === 0) { |
| | | uni.navigateTo({ |
| | |
| | | }) |
| | | } |
| | | } |
| | | // 获取空域信息列表 |
| | | async function getFlightAirspaceList() { |
| | | try { |
| | | const res = await flightAirspacePageInfoApi({ |
| | | current: 1, |
| | | size: 10, |
| | | }) |
| | | announcementList.value = res.data.data.records |
| | | } catch (error) { |
| | | uni.showToast({ |
| | | title: error.message, |
| | | icon: 'none', |
| | | duration: 2000, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // 获取通知公告列表 |
| | | async function getSysNoticeList() { |
| | | try { |
| | | const res = await sysNoticePageInfoApi({ |
| | | current: 1, |
| | | size: 10, |
| | | noticeType: 2, |
| | | }) |
| | | if (res.code === 200) { |
| | | announcementList.value = res.data.records |
| | | } |
| | | } catch (error) { |
| | | uni.showToast({ |
| | | title: error.message, |
| | | icon: 'none', |
| | | duration: 2000, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getFlightAirspaceList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | import pagesJson from "@/pages.json" |
| | | |
| | | // 路径常量 |
| | | export const HOME_PATH = "/pages/map/index" |
| | | export const HOME_PATH = "/pages/page/index" |
| | | export const LOGIN_PATH = "/pages/login/index" |
| | | export const ERROR404_PATH = "/pages/common/404/index" |
| | | export const ERROR404_PATH = "/subPackages/404/index" |
| | | |
| | | /** |
| | | * 解析路由地址 |
| | |
| | | // 假设有token值需要在头部需要携带 |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | if (accessToken) { |
| | | config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | // config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | config.header['authorization'] = accessToken; |
| | | } |
| | | if (detail?.areaCode) { |
| | | config.header['areaCode'] = detail.areaCode |
| | | } |
| | | // if (detail?.areaCode) { |
| | | // config.header['areaCode'] = detail.areaCode |
| | | // } |
| | | // 安全请求header |
| | | config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // 客户端认证参数 |
| | | config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | // config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | return config |
| | | }, config => { // 可使用async await 做异步操作 |
| | | return Promise.reject(config) |