ZaiZai 1 rok pred
rodič
commit
4b63c03d04

+ 1 - 1
public/version.json

@@ -1,3 +1,3 @@
 {
-  "value": "20230922101443"
+  "value": "20230922105919"
 }

+ 7 - 0
src/views/alter/admin/plan.vue

@@ -1,8 +1,15 @@
 <template>
+    <hc-card>
+        111
+    </hc-card>
 </template>
 
 <script setup>
+import { onMounted, ref } from 'vue'
 
+onMounted(() => {
+
+})
 </script>
 
 <style scoped lang="scss">

+ 296 - 3
src/views/user/index.vue

@@ -1,9 +1,302 @@
 <template>
-    <div>
-        111
-    </div>
+    <hc-card>
+        <div class="relative h-full flex">
+            <div class="mr-4 h-full w-[260px]">
+                <hc-card-item>
+                    <div class="hc-flex-center">
+                        <div class="user-avatar">
+                            <img class="avatar" :src="userInfo.avatar || avatarPng" alt="">
+                            <div class="avatar-upload" @click="setModalShowClick">
+                                <HcIcon fill name="camera" />
+                            </div>
+                        </div>
+                    </div>
+                    <div class="user-name">{{ userInfo.real_name || '游客' }}</div>
+                    <div class="user-menu-box">
+                        <hc-menu-simple :datas="menuOptions" :keys="menuKey" @change="handleMenuChange" />
+                    </div>
+                </hc-card-item>
+            </div>
+            <div class="h-full flex-1">
+                <hc-card-item v-if="menuKey === 'basic'" title="基础信息">
+                    <el-form :model="formUserModel" label-position="top" size="large">
+                        <el-row :gutter="20">
+                            <el-col :span="12">
+                                <el-form-item label="用户名称">
+                                    <el-input v-model="formUserModel.real_name" disabled />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="登录账号">
+                                    <el-input v-model="formUserModel.account" disabled />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="身份证号">
+                                    <el-input v-model="formUserModel.idNumber" disabled />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="绑定手机">
+                                    <el-input v-model="formUserModel.phone" disabled />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="所属角色">
+                                    <el-input v-model="formUserModel.roleName" disabled />
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="所属部门">
+                                    <el-input v-model="formUserModel.deptId" disabled />
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                    </el-form>
+                </hc-card-item>
+                <hc-card-item v-if="menuKey === 'password'" title="密码设置">
+                    <el-form
+                        ref="formUserPassRef"
+                        :model="formUserPassModel"
+                        :rules="formUserPassRules"
+                        label-position="top" size="large"
+                        style="max-width: 400px; margin: auto;"
+                    >
+                        <el-form-item label="原始密码" prop="oldPassword">
+                            <el-input
+                                v-model="formUserPassModel.oldPassword" placeholder="请输入原始密码"
+                                show-password type="password"
+                            />
+                        </el-form-item>
+                        <el-form-item label="新的密码" prop="newPassword">
+                            <el-input
+                                v-model="formUserPassModel.newPassword" placeholder="请输入新的密码"
+                                show-password type="password"
+                            />
+                        </el-form-item>
+                        <el-form-item label="确认新密码" prop="newPassword1">
+                            <el-input
+                                v-model="formUserPassModel.newPassword1" placeholder="请输入确认新密码"
+                                show-password type="password"
+                            />
+                        </el-form-item>
+                    </el-form>
+                    <template #action>
+                        <div class="hc-flex-center">
+                            <el-button :loading="saveUserLoading" hc-btn type="primary" @click="saveUserInfoClick">
+                                <HcIcon name="save" />
+                                <span>提交保存</span>
+                            </el-button>
+                        </div>
+                    </template>
+                </hc-card-item>
+            </div>
+        </div>
+        <!-- 文件上传 -->
+        <hc-upload-file ref="HcUploadFileRef" :options="uploadFileOptions" @success="uploadFileSuccess" />
+    </hc-card>
 </template>
 
 <script setup>
+import { onMounted, ref } from 'vue'
+import { useAppStore } from '~src/store'
+import userApi from '~api/userInfo/index'
+import avatarPng from '~src/assets/images/avatar.png'
+import { getHeader } from 'hc-vue3-ui'
+import { formValidate } from 'js-fast-way'
+const useState = useAppStore()
+import md5 from 'js-md5'
 
+
+const userInfo = ref(useState.getUserInfo)
+
+onMounted(() => {
+    uploadFileOptions.value = {
+        headers: getHeader(),
+        url: '/api/blade-resource/oss/endpoint/put-file',
+        accept: 'image/png,image/jpg,image/jpeg',
+        accept_tip: '只能上传图片(png、jpg、jpeg)文件',
+        multiple: false,
+    }
+    queryCurrentUserData()
+})
+
+//文件上传
+const HcUploadFileRef = ref(null)
+const uploadFileOptions = ref({})
+const setModalShowClick = () => {
+    HcUploadFileRef.value?.selectFile()
+}
+//文件上传完成
+const uploadFileSuccess = async ({ resData }) => {
+    const link = resData?.link ?? ''
+    const user_id = userInfo.value?.user_id ?? ''
+    if (link) {
+        const { error, code } = await userApi.updateUserInfo({
+            avatar: link,
+            id: user_id,
+        })
+        if (!error && code === 200) {
+            userInfo.value.avatar = link
+            window?.$message?.success('更换头像成功')
+            useState.setUserInfo(userInfo.value)
+        }
+    } else {
+        window?.$message?.warning('上传头像异常,请稍后再试')
+    }
+}
+
+//左侧菜单
+const menuKey = ref('basic')
+const menuOptions = ref([
+    { key: 'basic', label: '基础信息', icon: 'user-3' },
+    { key: 'password', label: '密码设置', icon: 'lock-unlock' },
+])
+const handleMenuChange = ({ key }) => {
+    if (key === 'basic' && menuKey.value !== key) {
+        queryCurrentUserData()
+    }
+    menuKey.value = key
+}
+
+//获取用户信息
+const formUserModel = ref({})
+const queryCurrentUserData = async () => {
+    const { error, code, data } = await userApi.queryCurrentUserData()
+    if (!error && code === 200) {
+        formUserModel.value = userInfo.value
+        formUserModel.value.deptId = data?.deptId || ''
+        formUserModel.value.idNumber = data?.idNumber || ''
+        formUserModel.value.roleName = data?.roleName || ''
+    }
+}
+
+//密码设置表单
+const formUserPassRef = ref(null)
+const formUserPassModel = ref({
+    oldPassword: '',
+    newPassword: '',
+    newPassword1: '',
+})
+const formUserPassRules = {
+    oldPassword: {
+        required: true,
+        trigger: 'blur',
+        message: '请输入原始密码',
+    },
+    newPassword: {
+        required: true,
+        validator(rule, value, callback) {
+            const pass = formUserPassModel.value.newPassword1
+            if (!value) {
+                callback(new Error('请输入新的密码'))
+            } else if (pass && value !== pass) {
+                callback(new Error('新的密码和确认新密码不一致'))
+            }
+            callback()
+        },
+        trigger: 'blur',
+    },
+    newPassword1: {
+        required: true,
+        validator(rule, value, callback) {
+            const pass = formUserPassModel.value.newPassword
+            if (!value) {
+                callback(new Error('请输入确认新密码'))
+            } else if (pass && value !== pass) {
+                callback(new Error('新的密码和确认新密码不一致'))
+            }
+            callback()
+        },
+        trigger: 'blur',
+    },
+}
+
+//保存数据
+const saveUserLoading = ref(false)
+const saveUserInfoClick = async () => {
+    const res = await formValidate(formUserPassRef.value)
+    if (res) {
+        const form = formUserPassModel.value
+        saveUserLoading.value = true
+        const { error, code } = await userApi.updatePassword({
+            oldPassword: md5(form?.oldPassword),
+            newPassword: md5(form?.newPassword),
+            newPassword1: md5(form?.newPassword1),
+            plaintextPassword: form?.newPassword,
+        })
+        if (!error && code === 200) {
+            saveUserLoading.value = false
+            window?.$message?.success('密码修改成功')
+            formUserPassModel.value = {
+                oldPassword: '',
+                newPassword: '',
+                newPassword1: '',
+            }
+        } else {
+            saveUserLoading.value = false
+        }
+    }
+}
 </script>
+
+<style scoped lang="scss">
+.user-avatar {
+    position: relative;
+    height: 100px;
+    width: 100px;
+    border: 2px solid #fff;
+    border-radius: 50%;
+    background: #d8d8d8;
+    margin-top: 16px;
+    margin-bottom: 12px;
+    box-shadow: 7px 7px 8px #365ca726, -7px -7px 8px #fff, 4px 4px 8px #365ca726, -4px -4px 8px #fff;
+    img {
+        border-radius: 50%;
+        display: block;
+        height: 100%;
+        -o-object-fit: cover;
+        object-fit: cover;
+        width: 100%;
+    }
+    .avatar-upload {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        position: absolute;
+        width: 24px;
+        height: 24px;
+        right: 0;
+        bottom: 0;
+        cursor: pointer;
+        color: #838791;
+        background: #f1f5f8;
+        border-radius: 50%;
+        transition: color .2s;
+        box-shadow: 4px 4px 8px #365ca726;
+        &:hover {
+            color: var(--el-color-primary);
+        }
+    }
+}
+.user-name {
+    position: relative;
+    color: #1a1a1a;
+    font-size: 16px;
+    font-weight: 700;
+    text-align: center;
+}
+</style>
+
+<style lang="scss">
+.user-menu-box {
+    position: relative;
+    margin-top: 20px;
+    .hc-menu-simple-box {
+        margin: -10px;
+        .item-box + .item-box {
+            margin-top: 16px;
+        }
+    }
+}
+</style>