吉安感知网项目-前端
shuishen
2026-01-15 91ce776ef98ad31db878650a0307b32de8dabef7
Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
16 files modified
23 files added
42 files deleted
2485 ■■■■■ changed files
applications/drone-command/src/views/system/user/FormDiaLog.vue 451 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/system/user/index.vue 504 ●●●●● patch | view | raw | blame | history
applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue 322 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/pages/login/index.vue 4 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/static/fonts/PANGMENZHENGDAOBIAOTITIMIANFEIBAN-2.TTF patch | view | raw | blame | history
uniapps/work-app/src/static/fonts/font.css 7 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages.json 35 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/equipmentManagement/index.vue 9 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/legalPolicy/index.vue 2 ●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/login/index.vue 29 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/page/index.vue 12 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/register/index.vue 28 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/pages/user/index.vue 4 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/add.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/add.svg 24 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/doc.svg 14 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/drone.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/drone.svg 26 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fj.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/flfg.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/flfg.svg 16 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fly-apply.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fly-apply.svg 43 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fxsq-bg.svg 33 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fxsq.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/fxsq.svg 20 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/kyxx.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/kyxx.svg 15 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/logo.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/logo.svg 6 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/my-sb.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/my-sb.svg 45 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/sp.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/sp.svg 5 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/add-task.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/add-work.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/add.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/add.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/drone.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/flzc-selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/flzc.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/home-selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/home.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_home.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_home1.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_home2.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_home_selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_home_selected.svg 10 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_list.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_list.svg 8 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_list_selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_list_selected.svg 8 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_me.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_me.svg 7 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_me_selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_me_selected.svg 7 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_order.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_order.svg 8 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_order_selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/icon_order_selected.svg 8 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/mainLogo.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/my-selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/my.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/sbgl-selected.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/tabbar/sbgl.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/user/default-header.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/user/droneLogo.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/user/showPsd.svg 11 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/static/images/user/user-bg.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/zczd.png patch | view | raw | blame | history
uniapps/work-wx/src/static/images/zczd.svg 20 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue 97 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/flightApplication/add.vue 35 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/flightApplication/index.vue 10 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/regulationsDetail/copy.vue 127 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/userDetail/infos/index.vue 4 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/userDetail/password/index.vue 220 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/workDetail/addWork/index.vue 52 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/workDetail/index.vue 68 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/workDetail/mapWork/index.vue 55 ●●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/workDetail/photoMagnify/index.vue 26 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/system/user/FormDiaLog.vue
New file
@@ -0,0 +1,451 @@
<template>
    <el-dialog v-model="visible" :title="titleEnum[dialogMode]" :close-on-click-modal="false" width="800px">
        <!-- 查看模式 -->
        <div v-if="readonly" class="view-mode">
            <el-row :gutter="16">
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">登录账号:</span>
                        {{ formData.account }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户姓名:</span>
                        {{ formData.realName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">手机号码:</span>
                        {{ formData.phone }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">电子邮箱:</span>
                        {{ formData.email }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户性别:</span>
                        {{ getSexLabel(formData.sex) }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户生日:</span>
                        {{ formData.birthday }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">所属角色:</span>
                        {{ formData.roleName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">所属部门:</span>
                        {{ formData.deptName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">用户编号:</span>
                        {{ formData.code }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">账号状态:</span>
                        {{ formData.statusName }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">到期时间:</span>
                        {{ formData.expireTime }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">次数限制:</span>
                        {{ formData.maxLoginNum }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">飞行开始时间:</span>
                        {{ formData.flightStartTime }}
                    </div>
                </el-col>
                <el-col :span="12">
                    <div class="view-item">
                        <span class="label">飞行结束时间:</span>
                        {{ formData.flightEndTime }}
                    </div>
                </el-col>
            </el-row>
        </div>
        <!-- 编辑/新增模式 -->
        <el-form v-else ref="formRef" :model="formData" :rules="rules" label-width="110px">
            <el-divider content-position="left">基础信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="登录账号" prop="account">
                        <el-input v-model="formData.account" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="密码" prop="password">
                        <el-input
                            v-model="formData.password"
                            type="password"
                            maxlength="50"
                            placeholder="请输入"
                            clearable
                            show-password
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="确认密码" prop="password2">
                        <el-input
                            v-model="formData.password2"
                            type="password"
                            maxlength="50"
                            placeholder="请输入"
                            clearable
                            show-password
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">详细信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户姓名" prop="realName">
                        <el-input v-model="formData.realName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="手机号码" prop="phone">
                        <el-input v-model="formData.phone" maxlength="20" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="电子邮箱" prop="email">
                        <el-input v-model="formData.email" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用户性别" prop="sex">
                        <el-select v-model="formData.sex" placeholder="请选择" clearable>
                            <el-option label="男" :value="1" />
                            <el-option label="女" :value="2" />
                            <el-option label="未知" :value="3" />
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用户生日" prop="birthday">
                        <el-date-picker
                            v-model="formData.birthday"
                            type="datetime"
                            placeholder="请选择"
                            format="YYYY-MM-DD HH:mm:ss"
                            value-format="YYYY-MM-DD HH:mm:ss"
                            clearable
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">职责信息</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户编号" prop="code">
                        <el-input v-model="formData.code" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属角色" prop="roleId">
                        <el-tree-select
                            v-model="formData.roleId"
                            :data="roleTree"
                            :props="treeProps"
                            node-key="id"
                            check-strictly
                            clearable
                            placeholder="请选择"
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属部门" prop="deptId">
                        <el-tree-select
                            v-model="formData.deptId"
                            :data="deptTree"
                            :props="deptTreeSelectProps"
                            node-key="id"
                            check-strictly
                            clearable
                            placeholder="请选择"
                        />
                    </el-form-item>
                </el-col>
            </el-row>
            <el-divider content-position="left">登录限制</el-divider>
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="到期时间" prop="expireTime">
                        <el-date-picker
                            v-model="formData.expireTime"
                            type="datetime"
                            placeholder="请选择"
                            format="YYYY-MM-DD HH:mm:ss"
                            value-format="YYYY-MM-DD HH:mm:ss"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="次数限制" prop="maxLoginNum">
                        <el-input v-model="formData.maxLoginNum" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="飞行开始时间" prop="flightStartTime">
                        <el-time-picker
                            v-model="formData.flightStartTime"
                            placeholder="请选择"
                            format="HH:mm"
                            value-format="HH:mm"
                            clearable
                        />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="飞行结束时间" prop="flightEndTime">
                        <el-time-picker
                            v-model="formData.flightEndTime"
                            placeholder="请选择"
                            format="HH:mm"
                            value-format="HH:mm"
                            clearable
                        />
                    </el-form-item>
                </el-col>
            </el-row>
        </el-form>
        <template #footer>
            <el-button @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
            <el-button v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
                确定
            </el-button>
        </template>
    </el-dialog>
</template>
<script setup>
import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { getUser, add, update } from '@/api/system/user'
import { getDeptTree } from '@/api/system/dept'
import { getRoleTree } from '@/api/system/role'
import func from '@/utils/func'
// 初始化表单
const initForm = () => ({
    account: '',
    password: '',
    password2: '',
    realName: '',
    phone: '',
    email: '',
    sex: null,
    birthday: '',
    code: '',
    roleId: '',
    deptId: '',
    expireTime: '',
    maxLoginNum: '',
    flightStartTime: '',
    flightEndTime: '',
})
const treeProps = {
    label: 'title',
    children: 'children',
}
const deptTreeSelectProps = {
    label: 'name',
    value: 'id',
    children: 'children',
}
const emit = defineEmits(['success'])
const formRef = ref(null)
const formData = ref(initForm())
const visible = defineModel()
const dialogMode = ref('add')
const submitting = ref(false)
const readonly = computed(() => dialogMode.value === 'view')
const titleEnum = ref({ edit: '编辑用户', view: '查看用户', add: '新增用户' })
const roleTree = ref([])
const deptTree = ref([])
// 密码验证
const validatePass = (rule, value, callback) => {
    if (value === '') {
        callback(new Error('请输入密码'))
    } else {
        callback()
    }
}
const validatePass2 = (rule, value, callback) => {
    if (value === '') {
        callback(new Error('请再次输入密码'))
    } else if (value !== formData.value.password) {
        callback(new Error('两次输入密码不一致!'))
    } else {
        callback()
    }
}
const rules = {
    account: [{ required: true, message: '请输入登录账号', trigger: 'blur' }],
    password: [{ required: true, validator: validatePass, trigger: 'blur' }],
    password2: [{ required: true, validator: validatePass2, trigger: 'blur' }],
    realName: [
        { required: true, message: '请输入用户姓名', trigger: 'blur' },
        { min: 2, max: 50, message: '姓名长度在2到50个字符', trigger: 'blur' },
    ],
    roleId: [{ required: true, message: '请选择所属角色', trigger: 'change' }],
    deptId: [{ required: true, message: '请选择所属部门', trigger: 'change' }],
}
// 获取性别标签
function getSexLabel(sex) {
    const map = { 1: '男', 2: '女', 3: '未知' }
    return map[sex] || ''
}
// 获取角色树
async function getRoleTreeData() {
    const res = await getRoleTree('000000')
    roleTree.value = res.data.data
}
// 获取部门树
async function getDeptTreeData() {
    const res = await getDeptTree('000000')
    deptTree.value = res.data.data
}
// 关闭弹框
function handleCancel() {
    visible.value = false
}
// 验证飞行时间
function validateFlightTime() {
    if (formData.value.flightStartTime && formData.value.flightEndTime) {
        const [startHours, startMinutes] = formData.value.flightStartTime.split(':').map(Number)
        const [endHours, endMinutes] = formData.value.flightEndTime.split(':').map(Number)
        const startTotalMinutes = startHours * 60 + startMinutes
        const endTotalMinutes = endHours * 60 + endMinutes
        if (endTotalMinutes < startTotalMinutes) {
            ElMessage.error('飞行结束时间不能小于飞行开始时间')
            return false
        }
    }
    return true
}
// 提交新增/编辑
async function handleSubmit() {
    const isValid = await formRef.value?.validate().catch(() => false)
    if (!isValid) return
    if (!validateFlightTime()) return
    submitting.value = true
    try {
        const submitData = { ...formData.value }
        submitData.roleId = func.toStr(submitData.roleId)
        submitData.name = submitData.realName
        if (dialogMode.value === 'add') {
            await add(submitData)
            ElMessage.success('新增成功')
        } else {
            await update(submitData)
            ElMessage.success('更新成功')
        }
        visible.value = false
        emit('success')
    } finally {
        submitting.value = false
    }
}
// 加载详情
async function loadDetail() {
    if (!formData.value.id) return
    const res = await getUser(formData.value.id)
    const data = res?.data?.data ?? {}
    // 处理 roleId
    if (data.roleId) {
        data.roleId = func.split(data.roleId)[0] || data.roleId
    }
    formData.value = data
}
// 打开弹框
async function open({ mode, row } = {}) {
    dialogMode.value = mode || 'add'
    if (dialogMode.value === 'add') {
        formData.value = initForm()
    } else {
        formData.value = { id: row.id }
        await loadDetail()
    }
}
onMounted(() => {
    getRoleTreeData()
    getDeptTreeData()
})
defineExpose({ open })
</script>
<style scoped lang="scss">
.view-mode {
    .view-item {
        padding: 10px 0;
        .label {
            color: #606266;
            font-weight: 500;
        }
    }
}
:deep(.el-select) {
    width: 100%;
}
:deep(.el-date-editor) {
    width: 100%;
}
:deep(.el-tree-select) {
    width: 100%;
}
</style>
applications/drone-command/src/views/system/user/index.vue
New file
@@ -0,0 +1,504 @@
<template>
    <basic-container>
        <!-- 左侧部门树 -->
        <el-row :gutter="16" class="user-container">
            <el-col :span="4">
                <div class="tree-box">
                    <el-scrollbar>
                        <el-tree
                            :data="deptTree"
                            :props="deptTreeProps"
                            node-key="id"
                            :load="loadDeptTree"
                            lazy
                            @node-click="handleDeptNodeClick"
                        />
                    </el-scrollbar>
                </div>
            </el-col>
            <!-- 右侧列表区 -->
            <el-col :span="20">
                <!-- 搜索表单 -->
                <el-form ref="queryParamsRef" :model="searchParams">
                    <el-row :gutter="16">
                        <el-col :span="5">
                            <el-form-item label="登录账号" prop="account">
                                <el-input v-model="searchParams.account" placeholder="请输入" clearable @clear="handleSearch" />
                            </el-form-item>
                        </el-col>
                        <el-col :span="5">
                            <el-form-item label="用户姓名" prop="realName">
                                <el-input v-model="searchParams.realName" placeholder="请输入" clearable @clear="handleSearch" />
                            </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 class="btn-group">
                    <el-button v-if="permission.user_add && !auditMode" type="primary" @click="openForm('add')">新增</el-button>
                    <el-button
                        v-if="permission.user_delete && !auditMode"
                        type="danger"
                        :disabled="!selectedIds.length"
                        @click="handleDelete()"
                    >
                        删除
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="success"
                        :disabled="!selectedIds.length"
                        @click="handleAuditPass"
                    >
                        通过
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="danger"
                        :disabled="!selectedIds.length"
                        @click="handleAuditRefuse"
                    >
                        拒绝
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && auditMode"
                        type="primary"
                        plain
                        @click="handleAuditBack"
                    >
                        返回
                    </el-button>
                    <el-button
                        v-if="permission.user_role && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleGrant"
                    >
                        角色配置
                    </el-button>
                    <el-button
                        v-if="permission.user_reset && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleReset"
                    >
                        密码重置
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="info"
                        plain
                        :disabled="!selectedIds.length"
                        @click="handleLock"
                    >
                        账号解封
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="success"
                        plain
                        @click="handleImport"
                    >
                        导入
                    </el-button>
                    <el-button
                        v-if="userInfo.role_name?.includes('admin') && !auditMode"
                        type="warning"
                        plain
                        @click="handleExport"
                    >
                        导出
                    </el-button>
                </div>
                <!-- 用户列表 -->
                <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="55" />
                    <el-table-column type="index" width="60" label="序号" />
                    <el-table-column prop="account" label="登录账号" />
                    <el-table-column prop="realName" label="用户姓名" />
                    <el-table-column prop="roleName" label="所属角色">
                        <template v-slot="{ row }">
                            <el-tag v-if="row.roleName">{{ row.roleName }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="deptName" label="所属部门">
                        <template v-slot="{ row }">
                            <el-tag v-if="row.deptName">{{ row.deptName }}</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="phone" label="手机号码" />
                    <el-table-column label="操作" width="180">
                        <template v-slot="{ row }">
                            <el-link v-if="permission.user_view" @click="openForm('view', row)" type="primary">查看</el-link>
                            <el-link v-if="permission.user_edit && !auditMode" @click="openForm('edit', row)" type="warning">
                                编辑
                            </el-link>
                            <el-link v-if="permission.user_delete && !auditMode" @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>
            </el-col>
        </el-row>
        <!-- 用户表单弹框 -->
        <FormDiaLog v-if="dialogVisible" v-model="dialogVisible" ref="dialogRef" @success="getList" />
        <!-- 角色配置弹框 -->
        <el-dialog title="用户角色配置" append-to-body v-model="roleBox" width="345px">
            <el-tree
                :data="roleGrantList"
                show-checkbox
                check-strictly
                default-expand-all
                node-key="id"
                ref="treeRoleRef"
                :default-checked-keys="roleTreeObj"
                :props="roleProps"
            ></el-tree>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="roleBox = false">取 消</el-button>
                    <el-button type="primary" @click="submitRole">确 定</el-button>
                </span>
            </template>
        </el-dialog>
        <!-- 导入弹框 -->
        <el-dialog title="用户数据导入" append-to-body v-model="excelBox" width="555px">
            <el-form :model="excelForm" label-width="100px">
                <el-form-item label="数据覆盖">
                    <el-switch v-model="excelForm.isCovered" :active-value="1" :inactive-value="0" />
                </el-form-item>
                <el-form-item label="模板上传">
                    <el-upload
                        :action="uploadAction"
                        :on-success="handleUploadSuccess"
                        accept=".xls,.xlsx"
                        :show-file-list="false"
                    >
                        <el-button type="primary">点击上传</el-button>
                    </el-upload>
                    <div class="upload-tip">请上传 .xls,.xlsx 标准格式文件</div>
                </el-form-item>
                <el-form-item label="模板下载">
                    <el-button type="primary" @click="handleTemplate">点击下载</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
    </basic-container>
</template>
<script setup>
import { computed, nextTick, onMounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useStore } from 'vuex'
import FormDiaLog from './FormDiaLog.vue'
import { getList as getListApi, remove, grant, resetPassword, unlock, auditPass, auditRefuse } from '@/api/system/user'
import { exportBlob } from '@/api/common'
import { getDeptTree, getDeptLazyTree } from '@/api/system/dept'
import { getRoleTree } from '@/api/system/role'
import website from '@/config/website'
import { getToken } from '@/utils/auth'
import { downloadXls } from '@/utils/util'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import func from '@/utils/func'
const store = useStore()
const userInfo = computed(() => store.getters.userInfo)
const permission = computed(() => store.getters.permission)
// 初始化搜索参数
const initSearchParams = () => ({
    account: '',
    realName: '',
    current: 1,
    size: 10,
})
const searchParams = ref(initSearchParams())
const total = ref(0)
const loading = ref(false)
const list = ref([])
const selectedIds = ref([])
const selectionList = ref([])
const queryParamsRef = ref(null)
const dialogRef = ref(null)
const dialogVisible = ref(false)
const auditMode = ref(false)
const treeDeptId = ref('')
// 部门树
const deptTree = ref([])
const deptTreeProps = {
    label: 'title',
    children: 'children',
    isLeaf: 'leaf',
}
// 角色配置
const roleBox = ref(false)
const roleGrantList = ref([])
const roleTreeObj = ref([])
const treeRoleRef = ref(null)
const roleProps = {
    label: 'title',
    value: 'key',
}
// 导入相关
const excelBox = ref(false)
const excelForm = ref({
    isCovered: 0,
})
const uploadAction = computed(() => `/blade-system/user/import-user?isCovered=${excelForm.value.isCovered}`)
provide('treeDeptId', treeDeptId)
// 加载部门树节点
async function loadDeptTree(node, resolve) {
    const parentId = node.level === 0 ? 0 : node.data.id
    const param = {
        parentId: parentId,
        level: node.level,
    }
    const res = await getDeptLazyTree(param)
    resolve(
        res.data.data.map(item => ({
            ...item,
            leaf: !item.hasChildren,
        }))
    )
}
// 部门节点点击
function handleDeptNodeClick(data) {
    treeDeptId.value = data.id
    searchParams.value.current = 1
    getList()
}
// 获取列表
async function getList() {
    loading.value = true
    try {
        const res = await getListApi(
            searchParams.value.current,
            searchParams.value.size,
            {
                account: searchParams.value.account,
                realName: searchParams.value.realName,
                status: auditMode.value ? 0 : 1,
            },
            treeDeptId.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 = initSearchParams()
    treeDeptId.value = ''
    getList()
}
// 删除
async function handleDelete(row) {
    const tips = row ? '该条' : '选中的项'
    await ElMessageBox.confirm(`确认删除${tips}吗?`, '提示', { type: 'warning' })
    const ids = row ? row.id : selectedIds.value.join(',')
    await remove(ids)
    ElMessage.success('删除成功')
    selectedIds.value = []
    getList()
}
// 勾选值设置
function handleSelectionChange(rows) {
    selectionList.value = rows
    selectedIds.value = rows.map(item => item.id)
}
// 角色配置
async function handleGrant() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    roleTreeObj.value = []
    if (selectionList.value.length === 1) {
        roleTreeObj.value = selectionList.value[0].roleId?.split(',') || []
    }
    const res = await getRoleTree()
    roleGrantList.value = res.data.data
    roleBox.value = true
}
// 提交角色配置
async function submitRole() {
    const roleList = treeRoleRef.value.getCheckedKeys().join(',')
    await grant(selectedIds.value.join(','), roleList)
    roleBox.value = false
    ElMessage.success('操作成功')
    getList()
}
// 密码重置
async function handleReset() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择账号密码重置为123456?', '提示', { type: 'warning' })
    await resetPassword(selectedIds.value.join(','))
    ElMessage.success('操作成功')
}
// 账号解封
async function handleLock() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择账号解封?', '提示', { type: 'warning' })
    await unlock(selectedIds.value.join(','))
    ElMessage.success('操作成功')
}
// 审核通过
async function handleAuditPass() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择数据通过审核?', '提示', { type: 'warning' })
    await auditPass(selectedIds.value.join(','))
    ElMessage.success('操作成功')
    getList()
}
// 审核拒绝
async function handleAuditRefuse() {
    if (selectedIds.value.length === 0) {
        ElMessage.warning('请选择至少一条数据')
        return
    }
    await ElMessageBox.confirm('确定将选择数据拒绝审核?', '提示', { type: 'warning' })
    await auditRefuse(selectedIds.value.join(','))
    ElMessage.success('操作成功')
    getList()
}
// 返回正常模式
function handleAuditBack() {
    auditMode.value = false
    getList()
}
// 导入
function handleImport() {
    excelBox.value = true
}
// 上传成功
function handleUploadSuccess() {
    excelBox.value = false
    getList()
    ElMessage.success('导入成功')
}
// 导出
function handleExport() {
    const account = func.toStr(searchParams.value.account)
    const realName = func.toStr(searchParams.value.realName)
    ElMessageBox.confirm('是否导出用户数据?', '提示', { type: 'warning' }).then(() => {
        NProgress.start()
        exportBlob(
            `/blade-system/user/export-user?${website.tokenHeader}=${getToken()}&account=${account}&realName=${realName}`
        ).then(res => {
            downloadXls(res.data, `用户数据表${new Date().toISOString().slice(0, 10)}.xlsx`)
            NProgress.done()
        })
    })
}
// 下载模板
function handleTemplate() {
    exportBlob(`/blade-system/user/export-template?${website.tokenHeader}=${getToken()}`).then(res => {
        downloadXls(res.data, '用户数据模板.xlsx')
    })
}
// 新增/编辑/查看 弹框
function openForm(mode, row) {
    dialogVisible.value = true
    nextTick(() => {
        dialogRef.value?.open({ mode, row })
    })
}
onMounted(() => {
    getList()
})
</script>
<style scoped lang="scss">
.user-container {
    height: 100%;
}
.tree-box {
    height: 100%;
    padding: 10px;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    :deep(.el-scrollbar) {
        height: 100%;
    }
}
.btn-group {
    margin-bottom: 16px;
}
.upload-tip {
    color: #999;
    font-size: 12px;
    margin-top: 8px;
}
</style>
applications/mobile-web-view/src/appPages/voiceCallDetail/index.vue
@@ -1,50 +1,53 @@
<template>
    <div class="call-container">
    <div class="call-container" :class="{'incoming-call': state === 'ringing'} ">
      <div class="content-wrapper">
        <div class="input-group">
            <div class="input-item">
                <span class="input-label">我的 userId:</span>
                <input v-model="uid" class="input-field" />
            </div>
            <div class="input-item">
                <span class="input-label">对方 userId:</span>
                <input v-model="peerUid" class="input-field" />
            </div>
        </div>
<!--        <div class="input-group">-->
<!--            <div class="input-item">-->
<!--                <span class="input-label">我的 userId:</span>-->
<!--                <input v-model="uid" class="input-field" />-->
<!--            </div>-->
<!--          -->
<!--            <div class="input-item">-->
<!--                <span class="input-label">对方 userId:</span>-->
<!--                <input v-model="peerUid" class="input-field" />-->
<!--            </div>-->
<!--        </div>-->
  
        <div class="button-group">
        <div class="button-group" v-if="false">
            <button @click="connectWS" :disabled="connected" class="btn btn-connect">连接WS</button>
        </div>
      <!--  头像-->
            <div class="contactAvatar">
                <img :src="defaultAvatar" alt=""></img>
            </div>
        <div class="button-group">
            <button @click="requestCall" :disabled="!connected || state!=='idle'" class="btn btn-call">呼叫</button>
            <button v-if="state==='ringing'" @click="acceptCall" class="btn btn-accept">接听</button>
            <button v-if="state==='ringing'" @click="rejectCall" class="btn btn-reject">拒绝</button>
            <button @click="hangup" :disabled="!connected || (state!=='calling' && state!=='in-call')" class="btn btn-hangup">挂断</button>
        </div>
        <div class="status-group">
            <strong class="status-text">状态:<span :style="{color: getStateColor(state)}">{{ state }}</span></strong>
         <div class="contactAvatar">
             <img :src="defaultAvatar" alt=""></img>
         </div>
         <div class="status-group">
            <strong v-if="state==='ringing'" class="status-text incoming-status">来电中...</strong>
            <strong v-if="state==='calling'" class="status-text calling-status">呼叫中...</strong>
        <!--    <strong class="status-text">状态:<span :style="{color: getStateColor(state)}">{{ state }}</span></strong>-->
            <strong v-if="state==='in-call'" class="status-text">通话时长:{{ durationText }}</strong>
        </div>
      </div>
      <div class="tip-message">
        <small>提示:若 getUserMedia 不可用,请用 https 或 localhost 访问页面。</small>
      </div>
      <div class="log-container">
        <div class="log-box">
            <div class="log-title">日志信息:</div>
            <pre class="log-content">{{ logText }}</pre>
        <div class="button-group">
            <button v-if="false" @click="requestCall" :disabled="!connected || state!=='idle'" class="btn btn-call">呼叫</button>
            <button v-if="state==='ringing'" @click="acceptCall" class="btn btn-accept incoming-accept">接听</button>
            <button v-if="state==='ringing'" @click="rejectCall" class="btn btn-reject incoming-reject">拒绝</button>
            <button v-if="state==='calling' || state==='in-call'" @click="hangup" class="btn btn-hangup">挂断</button>
        </div>
      </div>
<!--      <div class="tip-message">-->
<!--        <small>提示:若 getUserMedia 不可用,请用 https 或 localhost 访问页面。</small>-->
<!--      </div>-->
<!--      <div class="log-container">-->
<!--        <div class="log-box">-->
<!--            <div class="log-title">日志信息:</div>-->
<!--            <pre class="log-content">{{ logText }}</pre>-->
<!--        </div>-->
<!--      </div>-->
  
      <audio ref="remoteAudio" autoplay class="hidden-audio"></audio>
    </div>
@@ -131,6 +134,77 @@
    pingTimer = setInterval(() => {
      if (connected.value) send('ping', 'system', null)
    }, 25000)
  }
  // 来电提示相关
  let ringtoneAudio = null
  let vibrationTimer = null
  // 播放来电铃声
  function playRingtone() {
    // 创建音频对象(使用默认的系统提示音)
    ringtoneAudio = new Audio('data:audio/wav;base64,UklGRigAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQAAAAAAA==');
    ringtoneAudio.loop = true;
    ringtoneAudio.volume = 0.5;
    try {
      ringtoneAudio.play();
      log('🔊 开始播放来电铃声')
    } catch (e) {
      log('❌ 播放来电铃声失败:', String(e))
    }
  }
  // 停止来电铃声
  function stopRingtone() {
    if (ringtoneAudio) {
      try {
        ringtoneAudio.pause();
        ringtoneAudio.currentTime = 0;
        ringtoneAudio = null;
        log('🔇 停止播放来电铃声')
      } catch (e) {
        log('❌ 停止来电铃声失败:', String(e))
      }
    }
  }
  // 开始震动
  function startVibration() {
    // 检查浏览器是否支持震动 API
    if ('vibrate' in navigator) {
      // 震动模式:震动1秒,暂停0.5秒,重复
      const vibrationPattern = [1000, 500];
      try {
        navigator.vibrate(vibrationPattern);
        vibrationTimer = setInterval(() => {
          navigator.vibrate(vibrationPattern);
        }, 1500); // 每1.5秒重复一次震动模式
        log('📳 开始震动提示')
      } catch (e) {
        log('❌ 震动失败:', String(e))
      }
    } else {
      log('ℹ️ 当前浏览器不支持震动功能')
    }
  }
  // 停止震动
  function stopVibration() {
    if (vibrationTimer) {
      clearInterval(vibrationTimer);
      vibrationTimer = null;
    }
    if ('vibrate' in navigator) {
      try {
        navigator.vibrate(0); // 停止震动
        log('📳 停止震动提示')
      } catch (e) {
        log('❌ 停止震动失败:', String(e))
      }
    }
  }
  function stopPing() {
    if (pingTimer) clearInterval(pingTimer)
@@ -269,6 +343,11 @@
        state.value = 'ringing'
        log('📞 收到来电 call,来自', incomingFrom)
        // 开始来电提示(铃声和震动)
        playRingtone()
        startVibration()
        return
    }
@@ -384,13 +463,17 @@
  function acceptCall() {
    if (!incomingFrom) return
    acceptedByMe = true
    // 停止来电提示
    stopRingtone()
    stopVibration()
    // 先告诉对方我接听了(后端会把双方置忙)
    send('accept', incomingFrom, null)
    log('✅ 已点击接听,发送 accept 给', incomingFrom)
    state.value = 'calling'
    // 如果 offer 已经提前到达(我们暂存了),立刻 answer
    if (lastOfferSdp) {
      answerOffer(lastOfferSdp, incomingFrom)
@@ -400,7 +483,11 @@
  
  function rejectCall() {
    if (!incomingFrom) return
    // 停止来电提示
    stopRingtone()
    stopVibration()
    // 你后端没有 reject,用 busy 表示拒绝/不可接听
    send('busy', incomingFrom, null)
    log('❌ 已拒绝来电,发送 busy 给', incomingFrom)
@@ -410,6 +497,13 @@
    offeredByPeer = false
    lastOfferSdp = null
    state.value = 'idle'
    // 返回上一页(uni-app的语音通话列表页面)
    if (window.uni) {
      window.uni.navigateBack()
    } else {
      log('❌ uni对象不存在,无法返回上一页')
    }
  }
  
  async function startOffer() {
@@ -459,7 +553,10 @@
    } catch {}
  
    stopTimer()
    // 停止来电提示
    stopRingtone()
    stopVibration()
    if (pc) {
      pc.getSenders().forEach(s => s.track && s.track.stop())
      pc.close()
@@ -478,6 +575,13 @@
    lastOfferSdp = null
  
    state.value = 'idle'
    // 返回上一页(uni-app的语音通话列表页面)
    if (window.uni) {
      window.uni.navigateBack()
    } else {
      log('❌ uni对象不存在,无法返回上一页')
    }
}
onMounted(() => {
@@ -485,6 +589,15 @@
    console.log('接收参数', receiveParameters)
    // 解析URL参数
    parseUrlParams()
    // 自动连接WebSocket
    connectWS()
})
// 监听连接状态,连接成功后自动呼叫
watch(() => connected.value, (newVal) => {
    if (newVal && state.value === 'idle') {
        requestCall()
    }
})
  onBeforeUnmount(() => {
@@ -498,14 +611,31 @@
        padding: 20px;
        min-height: 100vh;
        font-family: Arial, sans-serif;
        background-color: #f5f5f5;
        transition: all 0.3s ease;
    }
    /* 来电时的全屏样式 */
    .call-container.incoming-call {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 99999;
        background-color: #ffffff;
        padding: 0;
    }
    .content-wrapper {
        display: flex;
        flex-direction: column;
        gap: 15px;
        gap: 20px;
        max-width: 600px;
        margin: 0 auto;
        height: 100vh;
        justify-content: center;
        align-items: center;
    }
    .input-group {
@@ -535,24 +665,56 @@
    .button-group {
        display: flex;
        gap: 10px;
        gap: 50px;
        flex-wrap: wrap;
        justify-content: center;
        margin-top: 80px;
    }
    .btn {
        padding: 10px 20px;
        padding: 15px 30px;
        color: white;
        border: none;
        border-radius: 4px;
        border-radius: 8px;
        cursor: pointer;
        font-size: 14px;
        transition: background-color 0.3s;
        font-size: 16px;
        font-weight: bold;
        transition: all 0.3s ease;
        min-width: 120px;
        &:disabled {
            opacity: 0.6;
            cursor: not-allowed;
        }
    }
    /* 来电时的接听和拒绝按钮样式 */
    .btn.incoming-accept, .btn.incoming-reject {
        width: 80px;
        height: 80px;
        border-radius: 50%;
        padding: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
    }
    .btn.incoming-accept {
        background-color: #4CAF50;
        transform: scale(1.1);
    }
    .btn.incoming-reject {
        background-color: #f44336;
    }
    .btn.incoming-accept:active {
        transform: scale(0.95);
    }
    .btn.incoming-reject:active {
        transform: scale(0.95);
    }
    .btn-connect {
@@ -573,17 +735,51 @@
    .btn-hangup {
        background-color: #9E9E9E;
        padding: 15px 40px;
        min-width: 150px;
    }
    .status-group {
        display: flex;
        flex-direction: column;
        gap: 5px;
        gap: 10px;
        align-items: center;
    }
    .status-text {
        font-size: 16px;
        font-size: 18px;
        color: #333;
        text-align: center;
        margin-bottom: 20px;
    }
    /* 来电状态样式 */
    .status-text.incoming-status {
        font-size: 24px;
        color: #333;
        font-weight: bold;
        animation: pulse 1.5s infinite;
    }
    .status-text.calling-status {
        font-size: 20px;
        color: #666;
    }
    /* 呼吸灯动画 */
    @keyframes pulse {
        0% {
            opacity: 1;
            transform: scale(1);
        }
        50% {
            opacity: 0.7;
            transform: scale(1.05);
        }
        100% {
            opacity: 1;
            transform: scale(1);
        }
    }
    .tip-message {
@@ -625,15 +821,31 @@
    .hidden-audio {
        display: none;
    }
    /* 头像样式 */
    .contactAvatar {
        width: 172rpx;
        height: 172rpx;
        width: 180px;
        height: 180px;
        display: flex;
        justify-content: center;
        align-items: center;
        img{
            width: 172rpx;
            height: 172rpx;
        margin-bottom: 40px;
        border-radius: 50%;
        background-color: #f0f0f0;
        overflow: hidden;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
        img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
    }
    /* 来电时的头像放大效果 */
    .call-container.incoming-call .contactAvatar {
        width: 220px;
        height: 220px;
        margin-bottom: 60px;
    }
  </style>
uniapps/work-app/src/pages/login/index.vue
@@ -203,12 +203,12 @@
  }
  .title {
    font-family: YouSheBiaoTiHei, YouSheBiaoTiHei;
    font-family: "PangMen";
    font-weight: 400;
    font-size: 52rpx;
    line-height: 82rpx;
    letter-spacing: 1px;
    text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18);
    text-shadow: 0px 8rpx 8rpx rgba(0, 0, 0, 0.18);
    text-align: center;
    font-style: normal;
    text-transform: none;
uniapps/work-app/src/static/fonts/PANGMENZHENGDAOBIAOTITIMIANFEIBAN-2.TTF
Binary files differ
uniapps/work-app/src/static/fonts/font.css
@@ -43,3 +43,10 @@
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "PangMen";
  src: url("PANGMENZHENGDAOBIAOTITIMIANFEIBAN-2.TTF") format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
uniapps/work-wx/src/pages.json
@@ -11,8 +11,7 @@
        {
            "path": "pages/page/index",
            "style": {
                "navigationBarTitleText": "首页",
                "navigationStyle": "custom"
                "navigationBarTitleText": "首页"
            }
        },
        {
@@ -24,23 +23,20 @@
        {
            "path": "pages/equipmentManagement/index",
            "style": {
                "navigationBarTitleText": "设备管理",
                "navigationStyle": "custom"
                "navigationBarTitleText": "设备管理"
            }
        },
        {
            "path": "pages/legalPolicy/index",
            "style": {
                "navigationBarTitleText": "法律政策",
                "navigationStyle": "custom"
                "navigationBarTitleText": "法律政策"
            }
        },
        {
            "path": "pages/user/index",
            "style": {
                "navigationBarTitleText": "我的",
                "navigationStyle": "custom"
                "navigationBarTitleText": "我的"
            }
        },
    {
@@ -101,13 +97,6 @@
                    }
                },
                {
                    "path": "workDetail/mapWork/index",
                    "style": {
                        "navigationBarTitleText": "地图展示",
                        "navigationStyle": "custom"
                    }
                },
                {
                    "path": "userDetail/infos/index",
                    "style": {
                        "navigationBarTitleText": "个人资料"
@@ -135,26 +124,26 @@
        "backgroundColor": "#ffffff",
        "list": [
            {
                "iconPath": "static/images/tabbar/icon_order.png",
                "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
                "iconPath": "static/images/tabbar/home.png",
                "selectedIconPath": "static/images/tabbar/home-selected.png",
                "pagePath": "pages/page/index",
                "text": "首页"
            },
            {
                "iconPath": "static/images/tabbar/icon_order.png",
                "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
                "iconPath": "static/images/tabbar/sbgl.png",
                "selectedIconPath": "static/images/tabbar/sbgl-selected.png",
                "pagePath": "pages/equipmentManagement/index",
                "text": "设备管理"
            },
            {
                "iconPath": "static/images/tabbar/icon_home1.png",
                "selectedIconPath": "static/images/tabbar/icon_home_selected.png",
                "iconPath": "static/images/tabbar/flzc.png",
                "selectedIconPath": "static/images/tabbar/flzc-selected.png",
                "pagePath": "pages/legalPolicy/index",
                "text": "法律政策"
            },
            {
                "iconPath": "static/images/tabbar/icon_me.png",
                "selectedIconPath": "static/images/tabbar/icon_me_selected.png",
                "iconPath": "static/images/tabbar/my.png",
                "selectedIconPath": "static/images/tabbar/my-selected.png",
                "pagePath": "pages/user/index",
                "text": "我的"
            }
uniapps/work-wx/src/pages/equipmentManagement/index.vue
@@ -24,8 +24,8 @@
<script setup>
import { reactive, ref } from 'vue'
import lbPng from '@/static/images/lb.png'
import addSvg from '@/static/images/add.svg'
import droneSvg from '@/static/images/drone.svg'
import addSvg from '@/static/images/add.png'
import droneSvg from '@/static/images/drone.png'
import { myDevicePageInfoApi, aircraftInfoPageInfoOfMyApi } from '@/api/index.js'
const equipmentList = ref([])
const noticeTitle = ref('')
@@ -35,11 +35,10 @@
  try {
    const res = await aircraftInfoPageInfoOfMyApi({
      current: 1,
      size: 10,
      size: 99,
      model:'',
      name: '',
    })
    console.log(8888888,res.data.data.records)
    equipmentList.value = res.data.data.records || []
  } catch (error) {
    console.error('获取设备列表失败:', error)
@@ -73,7 +72,7 @@
  height: 100%;
  display: flex;
  flex-direction: column;
  .u-search {
  :deep(.u-search) {
    padding: 10px 20px;
    height: 68rpx;
    flex: 0;
uniapps/work-wx/src/pages/legalPolicy/index.vue
@@ -96,7 +96,7 @@
  display: flex;
  flex-direction: column;
  
   .u-search {
   :deep(.u-search) {
    padding: 10px 20px;
    height: 68rpx;
    flex: 0;
uniapps/work-wx/src/pages/login/index.vue
@@ -9,24 +9,25 @@
        <input v-model="loginForm.username" placeholder="请输入用户名" />
      </div>
      <div class="pass-word">
        <input v-model="loginForm.password" :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码"/>
        <u-input type="password" border="bottom" v-model="loginForm.password" placeholder="请输入密码"></u-input>
        <!-- <input v-model="loginForm.password" :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码"/>
        <image v-if="!isShowPassword" :src="showPasswordSvg" @click="isShowPassword = !isShowPassword" />
        <image v-else :src="showPsdSvg"  @click="isShowPassword = !isShowPassword" />
        <image v-else :src="showPsdSvg"  @click="isShowPassword = !isShowPassword" /> -->
      </div>
    </view>
    <div class="remember-password">
      <view class="remember">
        <checkbox-group @change="toggleRemember">
        <!-- <checkbox-group @change="toggleRemember">
          <checkbox
            :checked="rememberPassword"
            color="#1D6FE9"
            style="transform: scale(0.7)"
          />
        </checkbox-group>
        记住密码
        记住密码 -->
      </view>
      <view class="forget">
        忘记密码
      <view class="forget" @click="forgetClick">
        忘记密码?
      </view>
    </div>
    <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button>
@@ -43,10 +44,8 @@
import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router";
import { ref } from "vue";
import logoSvg from "@/static/images/logo.svg";
import droneLogSvg from "@/static/images/user/droneLogo.svg";
import showPsdSvg from "@/static/images/user/showPsd.svg";
import showPasswordSvg from "@/static/images/show-password.svg";
import logoSvg from "@/static/images/logo.png";
import droneLogSvg from "@/static/images/user/droneLogo.png";
const droneSvg = getAssetsImage("/images/login/droneSvg.svg");
const usernameSvg = getAssetsImage("/images/login/username.svg");
@@ -151,6 +150,12 @@
  });
}
function forgetClick() {
  uni.navigateTo({
    url: "/subPackages/userDetail/password/index",
  });
}
// 从本地存储加载记住的密码
onMounted(() => {
  const savedUserInfo = uni.getStorageSync("rememberedUser");
@@ -176,8 +181,8 @@
  width: 100%;
  .logo {
    width: 127px;
    height: 51px;
    width: 67px;
    height: 67px;
    margin: 0 auto;
    margin-top: 162px;
    margin-bottom: 16px;
uniapps/work-wx/src/pages/page/index.vue
@@ -71,10 +71,10 @@
<script setup>
  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'
  import kyxxPng from '@/static/images/kyxx.png'
  import fxsqPng from '@/static/images/fxsq.png'
  import flfgPng from '@/static/images/flfg.png'
  import zczdPng from '@/static/images/zczd.png'
  import docSvg from '@/static/images/doc.png'
  import { sysNoticePageInfoApi, flightAirspacePageInfoApi } from '@/api/index'
const lbList = reactive([]);
@@ -225,8 +225,8 @@
  height: 100%;
  display: flex;
  flex-direction: column;
  .u-grid {
    margin-top: 20px;
  :deep(.u-grid) {
    margin-top: 40rpx;
    .grid-text {
      font-family: Source Han Sans CN, Source Han Sans CN;
      font-weight: 500;
uniapps/work-wx/src/pages/register/index.vue
@@ -4,7 +4,7 @@
        <view class="pageBg"></view>
        <view class="content">
           <view class="row">
             <view class="label"><span>*</span>手机号码</view>
             <view class="label"><span class="required">*</span>手机号码</view>
             <view class="input">
                <u-input input-align="right" border="bottom" v-model="formParams.userName" placeholder="请输入手机号码"></u-input>
             </view>
@@ -16,23 +16,23 @@
             </view>
           </view>
           <view class="row">
            <view class="label"><span>*</span>密码</view>
            <view class="label"><span class="required">*</span>密码</view>
             <view class="input">
                <u-input type="password" input-align="right" border="bottom" v-model="formParams.password" placeholder="请输入密码"></u-input>
             </view>
           </view>
           <view class="row">
            <view class="label"><span>*</span>确认密码</view>
            <view class="label"><span class="required">*</span>确认密码</view>
             <view class="input">
                <u-input type="password" input-align="right" border="bottom" v-model="formParams.password2" placeholder="请确认密码"></u-input>
             </view>
           </view>
           <view class="row">
            <view class="label"><span>*</span>验证码</view>
            <view class="label"><span class="required">*</span>验证码</view>
             <view class="input">
                <u-input input-align="right" border="bottom" v-model="formParams.code" placeholder="请输入验证码"></u-input>
             </view>
             <u-button class="getCode" :disabled="countDown > 0" @click="sendVerificationCode" type="primary" color="#007AFF">
             <u-button :disabled="countDown > 0" @click="sendVerificationCode" type="primary" color="#007AFF">
                {{ countDown > 0 ? `${countDown}s后重发` : '获取验证码' }}
            </u-button>
           </view>
@@ -214,7 +214,7 @@
        left: 0;
        width: 100%;
        height: 100%;
        background: url("@/static/images/user/userbg.svg")  no-repeat ;
        background-image: url("../../static/images/user/userbg.svg")  no-repeat ;
        background-size: 100%;
    }
    .content {
@@ -238,7 +238,7 @@
            font-weight: 400;
            font-size: 15px;
            color: #222324;
            span {
            .required {
                color: #FF4444;
            }
        }
@@ -251,15 +251,19 @@
        :deep(.u-icon--right) {
            display: none;
        }
        .getCode {
        :deep(.u-button) {
            width: 180rpx;
        }
    }
    .register {
        position: fixed;
        left: 24rpx;
        right: 24rpx;
        bottom: 126rpx;
        :deep(.u-button) {
            position: fixed;
            left: 24rpx;
            right: 24rpx;
            bottom: 126rpx;
            width: 80% !important;
            height: 100rpx !important;
        }
    }
}
</style>
uniapps/work-wx/src/pages/user/index.vue
@@ -55,7 +55,7 @@
import { getDeviceRegionApi } from "@/api/map.js";
import defaultAvatar  from '/static/images/defaultAvatar.svg'
import rightImage from '@/static/images/user/rightBtn.svg';
import showDefaultHeader from "@/static/images/user/default-header.svg";
import showDefaultHeader from "@/static/images/user/default-header.png";
const { setClipboardData, getClipboardData } = useClipboard();
//
// const rightImage = getAssetsImage("/images/user/rightBtn.svg");
@@ -100,7 +100,7 @@
  height: 100%;
}
.pageUser {
  background: url("@/static/images/user/userbg.svg")  no-repeat;
  background-image: url("../../static/images/user/userbg.svg")  no-repeat;
  background-size: 100%;
}
.userBox {
uniapps/work-wx/src/static/images/add.png
uniapps/work-wx/src/static/images/add.svg
File was deleted
uniapps/work-wx/src/static/images/doc.svg
File was deleted
uniapps/work-wx/src/static/images/drone.png
uniapps/work-wx/src/static/images/drone.svg
File was deleted
uniapps/work-wx/src/static/images/fj.svg
File was deleted
uniapps/work-wx/src/static/images/flfg.png
uniapps/work-wx/src/static/images/flfg.svg
File was deleted
uniapps/work-wx/src/static/images/fly-apply.png
uniapps/work-wx/src/static/images/fly-apply.svg
File was deleted
uniapps/work-wx/src/static/images/fxsq-bg.svg
File was deleted
uniapps/work-wx/src/static/images/fxsq.png
uniapps/work-wx/src/static/images/fxsq.svg
File was deleted
uniapps/work-wx/src/static/images/kyxx.png
uniapps/work-wx/src/static/images/kyxx.svg
File was deleted
uniapps/work-wx/src/static/images/logo.png

uniapps/work-wx/src/static/images/logo.svg
File was deleted
uniapps/work-wx/src/static/images/my-sb.png
uniapps/work-wx/src/static/images/my-sb.svg
File was deleted
uniapps/work-wx/src/static/images/sp.png
uniapps/work-wx/src/static/images/sp.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/add-task.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/add-work.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/add.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/add.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/drone.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/flzc-selected.png
uniapps/work-wx/src/static/images/tabbar/flzc.png
uniapps/work-wx/src/static/images/tabbar/home-selected.png
uniapps/work-wx/src/static/images/tabbar/home.png
uniapps/work-wx/src/static/images/tabbar/icon_home.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_home1.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_home2.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_home_selected.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_home_selected.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_list.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_list.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_list_selected.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_list_selected.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_me.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_me.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_me_selected.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_me_selected.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_order.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_order.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/icon_order_selected.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/icon_order_selected.svg
File was deleted
uniapps/work-wx/src/static/images/tabbar/mainLogo.png
Binary files differ
uniapps/work-wx/src/static/images/tabbar/my-selected.png
uniapps/work-wx/src/static/images/tabbar/my.png
uniapps/work-wx/src/static/images/tabbar/sbgl-selected.png
uniapps/work-wx/src/static/images/tabbar/sbgl.png
uniapps/work-wx/src/static/images/user/default-header.png
uniapps/work-wx/src/static/images/user/droneLogo.png
uniapps/work-wx/src/static/images/user/showPsd.svg
File was deleted
uniapps/work-wx/src/static/images/user/user-bg.png
uniapps/work-wx/src/static/images/zczd.png
uniapps/work-wx/src/static/images/zczd.svg
File was deleted
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
@@ -220,53 +220,54 @@
                    placeholder="请输入"
            ></u-input>
        </u-form-item>
        <u-button class="submit-button-wrapper" color="#1D6FE9" size="large" @click="submitForm">
            注册
        </u-button>
            <!-- 飞行器型号 -->
    <u-picker
        :show="showType"
        :columns="[typeList]"
        keyName="label"
        @confirm="onPickerConfirmType"
        @cancel="showType = false"
    />
    <!-- 飞行器厂商 -->
    <u-picker
        :show="showManufacturer"
        :columns="[manufacturerList]"
        keyName="label"
        @confirm="onPickerConfirmManufacturer"
        @cancel="showManufacturer = false"
    />
    <u-picker
        :show="showIsModified"
        :columns="[actionsModified]"
        keyName="label"
        @confirm="onPickerConfirm"
        @cancel="showIsModified = false"
    />
    <u-picker
        :show="showHasInsurance"
        :columns="[actionsHasInsurance]"
        keyName="label"
        @confirm="onPickerConfirmHasInsurance"
        @cancel="showHasInsurance = false"
    />
    <u-datetime-picker
      :show="showPurchaseDate"
      v-model="birthdayValue"
      mode="date"
      @confirm="onPurchaseDate"
      @cancel="showPurchaseDate = false"
    />
    <!-- 所属区域 -->
     <u-cascader
        show="show"
        v-model="value"
        :data="areaData"
    ></u-cascader>
        <!-- 飞行器型号 -->
        <u-picker
            :show="showType"
            :columns="[typeList]"
            keyName="label"
            @confirm="onPickerConfirmType"
            @cancel="showType = false"
        />
        <!-- 飞行器厂商 -->
        <u-picker
            :show="showManufacturer"
            :columns="[manufacturerList]"
            keyName="label"
            @confirm="onPickerConfirmManufacturer"
            @cancel="showManufacturer = false"
        />
        <u-picker
            :show="showIsModified"
            :columns="[actionsModified]"
            keyName="label"
            @confirm="onPickerConfirm"
            @cancel="showIsModified = false"
        />
        <u-picker
            :show="showHasInsurance"
            :columns="[actionsHasInsurance]"
            keyName="label"
            @confirm="onPickerConfirmHasInsurance"
            @cancel="showHasInsurance = false"
        />
        <u-datetime-picker
        :show="showPurchaseDate"
        v-model="birthdayValue"
        mode="date"
        @confirm="onPurchaseDate"
        @cancel="showPurchaseDate = false"
        />
        <!-- 所属区域 -->
        <u-cascader
            show="show"
            v-model="value"
            :data="areaData"
        ></u-cascader>
    </u-form>
    <u-button @click="submitForm" color="#1D6FE9">提交</u-button>
    <!-- <u-button class="submit-button-wrapper" color="#1D6FE9" size="large" @click="submitForm">
            注册
        </u-button> -->
</view>
</template>
<script setup>
@@ -585,9 +586,11 @@
        padding: 24rpx;
    }
    .submit-button-wrapper {
    :deep(.u-button) {
        width: 80%;
        padding: 28rpx;
        border-radius: 8rpx 8rpx 8rpx 8rpx;
        margin-bottom: 20rpx;
    }
    
    :deep(.u-form-item) {
uniapps/work-wx/src/subPackages/flightApplication/add.vue
@@ -290,13 +290,9 @@
                ></up-icon>
            </template>
        </u-form-item>
        <u-button class="submit-button-wrapper" color="#1D6FE9" size="large" @click="submitForm">
        <!-- <u-button class="submit-button-wrapper" color="#1D6FE9" size="large" @click="submitForm">
            飞行申请
        </u-button>
        <!-- 飞任务类型 -->
        <view class="attention">
            注:新增空域/航线/飞手等前往吉安市低空经济服务一体化
        </view>
        </u-button> -->
    <u-picker
        :show="isShowFlightTaskType"
        :columns="[actionsFlightTaskType]"
@@ -377,7 +373,11 @@
        @cancel="isShowFlightRouteInfo = false"
    />
    </u-form>
    <u-button @click="submitForm" color="#1D6FE9">飞行申请</u-button>
    <!-- 飞任务类型 -->
    <view class="attention">
        注:新增空域/航线/飞手等前往吉安市低空经济服务一体化
    </view>
</view>
</template>
<script setup>
@@ -751,6 +751,20 @@
        margin-bottom: 24rpx;
        padding-left: 0rpx !important;
    }
    :deep(.u-button) {
        width: 80%;
        padding: 28rpx;
        border-radius: 8rpx 8rpx 8rpx 8rpx;
        margin-bottom: 20rpx;
    }
    .attention {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #1D6FE9;
        //  margin-top: 24rpx;
        text-align: center;
    }
    .select-wrapper {
        position: relative;
        width: 100%;
@@ -785,13 +799,6 @@
        // width: 80%;
        // height: 100rpx;
        border-radius: 8rpx 8rpx 8rpx 8rpx;
    }
    .attention {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #1D6FE9;
         margin-top: 24rpx;
    }
    :deep(.u-form-item) {
        margin-bottom: 40rpx;
uniapps/work-wx/src/subPackages/flightApplication/index.vue
@@ -33,10 +33,10 @@
</view>
</template>
<script setup>
    import spSvg from '@/static/images/sp.svg'
    import spSvg from '@/static/images/sp.png'
    import { flightPlanPageInfoApi } from '@/api/index.js'
    import fxsqSvg from '@/static/images/fly-apply.svg'
    import mysbSvg from '@/static/images/my-sb.svg'
    import fxsqSvg from '@/static/images/fly-apply.png'
    import mysbSvg from '@/static/images/my-sb.png'
import { ref } from 'vue'
@@ -130,7 +130,7 @@
    .header-top {
        width: 100%;
        height: 350rpx;
        background: url('@/static/images/fxsq-bg.png') no-repeat center center;
        background: url('@/static/images/fxsq-bg.png') no-repeat center;
        background-size: 100% 100%;
        position: fixed;
        top: 0;
@@ -170,7 +170,7 @@
            }
        }
    }
     .u-search {
     :deep(.u-search) {
        position: absolute;
        width: 90%;
        left: 50%;
uniapps/work-wx/src/subPackages/regulationsDetail/copy.vue
File was deleted
uniapps/work-wx/src/subPackages/userDetail/infos/index.vue
@@ -41,7 +41,7 @@
</template>
<script setup>
    import showDefaultHeader from "@/static/images/user/default-header.svg";
    import showDefaultHeader from "@/static/images/user/default-header.png";
    import {
        getEnvObj,
        getWebViewUrl
@@ -252,7 +252,7 @@
        left: 0;
        width: 100%;
        height: 100%;
        background: url("@/static/images/user/userbg.svg")  no-repeat ;
        background-image: url("../../../static/images/user/userbg.svg")  no-repeat ;
        background-size: 100%;
    }
    .avatarBox {
uniapps/work-wx/src/subPackages/userDetail/password/index.vue
@@ -1,6 +1,6 @@
<!-- 修改密码 -->
<template>
    <view class="container">
    <view class="user-password">
        <view class="pageBg"></view>
        <view class="detailBox">
            <div class="detailCon">
@@ -20,7 +20,7 @@
                <div class="orderRow">
                    <div class="rowTitle">验证码</div>
                    <input type="text" v-model="passwordForm.code" placeholder="请输入验证码" class="input-item" />
                    <u-button class="getCode" :disabled="countDown > 0" @click="sendVerificationCode" type="primary" color="#007AFF">
                    <u-button :disabled="countDown > 0" @click="sendVerificationCode" type="primary" color="#007AFF">
                        {{ countDown > 0 ? `${countDown}s后重发` : '获取验证码' }}
                    </u-button>
                </div>
@@ -34,6 +34,7 @@
</template>
<script setup>
    import userbgSvg from "@/static/images/user/userbg.svg";
    import {
        useUserStore
    } from "@/store/index.js";
@@ -246,126 +247,125 @@
</script>
<style lang="scss" scoped>
    .container {
    .user-password {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        position: relative;
    }
    .pageBg {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: url("@/static/images/user/userbg.svg")  no-repeat ;
        background-size: 100%;
    }
    .detailBox {
        position: absolute;
        top: 180rpx;
        // margin-top: 40rpx;
        width: 702rpx;
        min-height: 326rpx;
        background: #FFFFFF;
        border-radius: 12rpx;
        box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
        .detailCon {
            padding: 0 24rpx;
        .pageBg {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-image: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png");
            background-size: 100%;
        }
        .orderRow {
        .detailBox {
            position: absolute;
            top: 180rpx;
            // margin-top: 40rpx;
            width: 702rpx;
            min-height: 326rpx;
            background: #FFFFFF;
            border-radius: 12rpx;
            box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
            .detailCon {
                padding: 0 24rpx;
            }
            .orderRow {
                display: flex;
                justify-content: space-between;
                align-items: center;
                height: 96rpx;
                border-bottom: 2rpx 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;
                }
                input.input-item {
                    text-align: right;
                    border: none !important;
                    background: transparent !important;
                    box-shadow: none !important;
                    padding: 0 !important;
                    margin: 0 !important;
                    height: auto !important;
                    outline: none;
                    font-size: 30rpx;
                    color: #222324;
                    font-family: Source Han Sans CN, Source Han Sans CN;
                }
        :deep(.uni-input-placeholder) {
            color: #D5D5D5;
        }
                input.input-item::placeholder {
                    font-size: 30rpx;
                }
                // .code-container {
                //     display: flex;
                //     align-items: center;
                //     justify-content: flex-end;
                //     width: 100%;
                // }
                .send-code-btn {
                    margin-left: 20rpx;
                    width: 200rpx;
                    height: 70rpx;
                    line-height: 70rpx;
                    font-size: 26rpx;
                    background: #f5f5f5;
                    color: #666;
                    border-radius: 8rpx;
                }
                .send-code-btn:disabled {
                    background: #e0e0e0;
                    color: #999;
                }
                :deep(.u-button){
                    width: 180rpx !important;
                    height: 60rpx !important;
                }
            }
        }
        .btngroup {
            display: flex;
            justify-content: space-between;
            align-items: center;
            height: 96rpx;
            border-bottom: 2rpx 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;
            }
            input.input-item {
                text-align: right;
                border: none !important;
                background: transparent !important;
                box-shadow: none !important;
                padding: 0 !important;
                margin: 0 !important;
                height: auto !important;
                outline: none;
                font-size: 30rpx;
                color: #222324;
                font-family: Source Han Sans CN, Source Han Sans CN;
            }
      :deep(.uni-input-placeholder) {
        color: #D5D5D5;
      }
            input.input-item::placeholder {
                font-size: 30rpx;
            }
            // .code-container {
            //     display: flex;
            //     align-items: center;
            //     justify-content: flex-end;
            //     width: 100%;
            // }
            .send-code-btn {
                margin-left: 20rpx;
                width: 200rpx;
                height: 70rpx;
                line-height: 70rpx;
                font-size: 26rpx;
                background: #f5f5f5;
                color: #666;
                border-radius: 8rpx;
            }
            .send-code-btn:disabled {
                background: #e0e0e0;
                color: #999;
            position: absolute;
            bottom: 150rpx;
            :deep(.u-button){
                width: 276rpx !important;
                height: 100rpx !important;
            }
        }
    }
    .btngroup {
        display: flex;
        position: absolute;
        bottom: 150rpx;
    }
        :deep(.u-button:first-child) {
            margin-right: 30rpx !important;
        }
    :deep(.u-button:first-child) {
        margin-right: 30rpx !important;
        .custom-style {
            width: 276rpx;
            height: 100rpx;
            font-family: "Source Han Sans CN";
            font-weight: 400;
            font-size: 36rpx;
        }
    }
    .custom-style {
        width: 276rpx;
        height: 100rpx;
          font-family: "Source Han Sans CN";
        font-weight: 400;
        font-size: 36rpx;
    }
    :deep(.u-button.data-v-461e713c){
        width: 276rpx !important;
        height: 100rpx !important;
    }
    .getCode {
        margin-left: 20rpx;
            width: 180rpx;
        }
</style>
uniapps/work-wx/src/subPackages/workDetail/addWork/index.vue
File was deleted
uniapps/work-wx/src/subPackages/workDetail/index.vue
File was deleted
uniapps/work-wx/src/subPackages/workDetail/mapWork/index.vue
File was deleted
uniapps/work-wx/src/subPackages/workDetail/photoMagnify/index.vue
File was deleted