教学资源页面开发,分页,音频,类型图,下载,个人中心资料修改,密码修改,校验
6个文件已修改
3个文件已添加
546 ■■■■ 已修改文件
components.d.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/static/icons/file_type_audio.png 补丁 | 查看 | 原始文档 | blame | 历史
public/static/icons/file_type_excel.png 补丁 | 查看 | 原始文档 | blame | 历史
public/static/icons/file_type_ppt.png 补丁 | 查看 | 原始文档 | blame | 历史
src/api/modules/file.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/modules/personalCenter.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/folder/index.vue 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personal-center/index.vue 171 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components.d.ts
@@ -11,7 +11,11 @@
    ElButton: typeof import('element-plus/es')['ElButton']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElCollapse: typeof import('element-plus/es')['ElCollapse']
    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
    ElCountdown: typeof import('element-plus/es')['ElCountdown']
    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
    ElDialog: typeof import('element-plus/es')['ElDialog']
    ElDrawer: typeof import('element-plus/es')['ElDrawer']
    ElDropdown: typeof import('element-plus/es')['ElDropdown']
    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
@@ -23,9 +27,11 @@
    ElInput: typeof import('element-plus/es')['ElInput']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElPagination: typeof import('element-plus/es')['ElPagination']
    ElProgress: typeof import('element-plus/es')['ElProgress']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSlider: typeof import('element-plus/es')['ElSlider']
    ElTable: typeof import('element-plus/es')['ElTable']
    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
    ElTabPane: typeof import('element-plus/es')['ElTabPane']
public/static/icons/file_type_audio.png
public/static/icons/file_type_excel.png
public/static/icons/file_type_ppt.png
src/api/modules/file.js
@@ -1,5 +1,5 @@
import service from "@/api";
export const getFileList = (getData = {introduction: '', subjectId: '', contentType: ''}) => {
export const getFileList = (getData) => {
  return service.get('/api/student/education/resource/page', {params: getData});
};
src/api/modules/personalCenter.js
@@ -7,3 +7,9 @@
    },
  });
};
export const userUpdate = (postData) => {
  return service.post("/api/student/user/update", postData);
};
export const passwordUpdate = (postData) => {
  return service.post("/api/student/user/update/password", postData);
};
src/main.js
@@ -1,23 +1,26 @@
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import 'xgplayer/dist/index.min.css'; // 引入西瓜视频样式
import router from '@/router/index.js';
import pinia from './store';
import VueUeditorWrap from 'vue-ueditor-wrap';
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import "xgplayer/dist/index.min.css"; // 引入西瓜视频样式
import router from "@/router/index.js";
import pinia from "./store";
import VueUeditorWrap from "vue-ueditor-wrap";
import ZhLocale from "element-plus/es/locale/lang/zh-cn"; // 中文
const app = createApp(App);
app.use(router);
app.use(pinia);
app.use(ElementPlus);
app.use(ElementPlus, {
  locale: ZhLocale,
});
app.use(VueUeditorWrap);
app.mount('#app');
app.mount("#app");
// 全局vue异常捕获
app.config.errorHandler = (error, vm, info) => {
  console.error('Vue 发生错误:', error);
  console.error('错误信息:', info);
  router.replace('/index');
};
  console.error("Vue 发生错误:", error);
  console.error("错误信息:", info);
  router.replace("/index");
};
src/views/folder/index.vue
@@ -1,63 +1,129 @@
<template>
  <div class="train-container w-screen h-screen bg-slate-50 flex flex-col items-center">
  <div
    class="train-container w-screen h-screen bg-slate-50 flex flex-col items-center"
  >
    <NormalHeader class="shrink-0"></NormalHeader>
    <div class="list-container container grow relative">
      <div class="list-content absolute top-0 bottom-0 left-0 right-0 py-4">
        <div class="list-wrapper w-full h-full">
          <el-card class="h-full" :body-style="{ height: '100%' }">
            <div class="card-wrapper w-full h-full flex flex-col px-8 box-border">
              <div class="card-header flex justify-between items-center shrink-0">
            <div
              class="card-wrapper w-full h-full flex flex-col px-8 box-border"
            >
              <div
                class="card-header flex justify-between items-center shrink-0"
              >
                <div class="header-search flex items-center">
                  <el-input v-model="searchText" placeholder="请输入搜索内容" class="long-input" :prefix-icon="Search"/>
                  <el-select v-model="searchSubject" placeholder="请选择科目" class="ml-4 long-select" clearable>
                    <el-option v-for="item in subjectList" :key="item.id" :label="item.name" :value="item.id"/>
                  </el-select>
                  <el-select v-model="searchContentType" placeholder="请选择文件类型" class="ml-4 long-select" clearable>
                  <el-input
                    v-model="searchText"
                    placeholder="请输入搜索内容"
                    class="long-input"
                    :prefix-icon="Search"
                  />
                  <el-select
                    v-model="searchSubject"
                    placeholder="请选择科目"
                    class="ml-4 long-select"
                    clearable
                  >
                    <el-option
                        v-for="item in contentTypeList"
                        :key="item.value"
                        :label="item.name"
                        :value="item.value">
                      v-for="item in subjectList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                    />
                  </el-select>
                  <el-select
                    v-model="searchContentType"
                    placeholder="请选择文件类型"
                    class="ml-4 long-select"
                    clearable
                  >
                    <el-option
                      v-for="item in contentTypeList"
                      :key="item.value"
                      :label="item.name"
                      :value="item.value"
                    >
                    </el-option>
                  </el-select>
                  <el-button type="primary" class="ml-4" @click="searchFile">搜索</el-button>
                  <el-button type="primary" class="ml-4" @click="searchFile"
                    >搜索</el-button
                  >
                </div>
              </div>
              <div class="card-main flex-1 my-5 relative">
                <div class="main-content absolute top-0 bottom-0 left-0 right-0">
                <div
                  class="main-content absolute top-0 bottom-0 left-0 right-0"
                >
                  <el-table :data="fileList" height="100%" v-loading="loading">
                    <el-table-column label="文件名称">
                      <template #default="scope">
                        <div class="row-info">
                          <div class="icon">
                            <img :src="getIcon(scope.row.contentType)" class="width-img"/>
                            <img
                              :src="getIcon(scope.row.contentType)"
                              class="width-img"
                            />
                          </div>
                          <div class="label">{{ scope.row.introduction }}</div>
                        </div>
                      </template>
                    </el-table-column>
                    <el-table-column prop="className" label="班级" align="center"/>
                    <el-table-column prop="typeName" label="科目" align="center"/>
                    <el-table-column prop="updateTime" label="上传时间" align="center"/>
                    <el-table-column
                      prop="className"
                      label="班级"
                      align="center"
                    />
                    <el-table-column
                      prop="typeName"
                      label="科目"
                      align="center"
                    />
                    <el-table-column
                      prop="updateTime"
                      label="上传时间"
                      align="center"
                    />
                    <el-table-column>
                      <template #default="scope">
                        <el-button link type="primary" @click.prevent="checkRow(scope.row)">
                        <el-button
                          link
                          type="primary"
                          @click.prevent="checkRow(scope.row)"
                          v-if="
                            scope.row.contentType == 'video' ||
                            scope.row.contentType == 'audio'
                          "
                        >
                          查看
                        </el-button>
                        <el-button
                          link
                          type="primary"
                          @click.prevent="download(scope.row)"
                          v-else
                        >
                          下载
                        </el-button>
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
              <div class="card-footer flex justify-center mb-7 shrink-0">
                <el-pagination background layout="prev, pager, next" :total="fileList.length"
                               :default-page-size="20"
                               :currentPage="currentIndex"
                               :hide-on-single-page="true"
                               @current-change="handleCurrentChange"/>
                <el-pagination
                  background
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="total"
                  :page-sizes="[10, 20, 50]"
                  :page-size="pageSize"
                  :currentPage="currentIndex"
                  @size-change="handleSizeChange"
                  @current-change="handleCurrentChange"
                />
              </div>
            </div>
          </el-card>
@@ -81,87 +147,126 @@
    <!-- image查看 -->
    <div class="image-container" v-show="imageViewer">
      <el-image-viewer :url-list="imageList" @close="closeViewer"></el-image-viewer>
      <el-image-viewer
        :url-list="imageList"
        @close="closeViewer"
      ></el-image-viewer>
    </div>
    <!-- 视频查看 -->
    <div class="video-container" v-show="videoViewer">
    <div class="video-container" v-if="videoViewer">
      <VideoViewer :videoUrl="videoUrl"></VideoViewer>
      <div class="close-btn">
        <el-button type="danger" size="large" circle @click="closeViewer">
          <template #icon>
            <el-icon :size="20">
              <Close/>
              <Close />
            </el-icon>
          </template>
        </el-button>
      </div>
    </div>
    <!-- 弹窗 -->
    <el-drawer v-model="fileViewer" direction="btt" size="90%" :before-close="handleClose">
        <DocumentViewer :fileUrl="fileUrl"></DocumentViewer>
    </el-drawer>
    <!-- <el-drawer
      v-model="fileViewer"
      direction="btt"
      size="90%"
      :before-close="handleClose"
    >
      <DocumentViewer :fileUrl="fileUrl"></DocumentViewer>
    </el-drawer> -->
  </div>
</template>
<script setup>
import {ref, onMounted, onBeforeUnmount} from 'vue';
import {storeToRefs} from 'pinia';
import {Close} from '@element-plus/icons-vue';
import NormalHeader from '@/components/NormalHeader/index.vue';
import {Search} from '@element-plus/icons-vue';
import {getFileList} from '@/api/modules/file.js';
import {getSubjectList} from '@/api/modules/subject.js';
import { ref, onMounted, onBeforeUnmount } from "vue";
import { storeToRefs } from "pinia";
import { Close } from "@element-plus/icons-vue";
import NormalHeader from "@/components/NormalHeader/index.vue";
import { Search } from "@element-plus/icons-vue";
import { getFileList } from "@/api/modules/file.js";
import { getSubjectList } from "@/api/modules/subject.js";
import PDFViewer from '@/components/PDFViewer/index.vue';
import VideoViewer from '@/components/VideoViewer/index.vue';
import PDFViewer from "@/components/PDFViewer/index.vue";
import VideoViewer from "@/components/VideoViewer/index.vue";
import DocumentViewer from "@/components/DocumentViewer/index.vue";
import {useUserStore} from '@/store/index.js';
import useWebScoket from '@/hooks/useWebScoket.js';
import { useUserStore } from "@/store/index.js";
import useWebScoket from "@/hooks/useWebScoket.js";
const userStore = useUserStore();
const {userInfo} = storeToRefs(userStore);
const {status, message, error, connect, disconnect, sendMessage} = useWebScoket({
  url: 'ws://42.193.1.25:8000/websocket/' + userInfo.value.id,
  heartBeatData: 'ping'
});
const { userInfo } = storeToRefs(userStore);
const { status, message, error, connect, disconnect, sendMessage } =
  useWebScoket({
    url: "ws://42.193.1.25:8000/websocket/" + userInfo.value.id,
    heartBeatData: "ping",
  });
const time = ref(null);
const fileType = {
  'img': {
    iconPath: '/static/icons/file_type_image.png',
  img: {
    iconPath: "/static/icons/file_type_image.png",
    handle: (item) => {
      console.log(item);
      imageViewer.value = true;
      imageList.value = ['/api/files/' + item.contentUrl.url];
      imageList.value = ["/api/files/" + item.contentUrl.url];
      resendMessage();
    }
    },
  },
  'video': {
    iconPath: '/static/icons/file_type_video.png',
  video: {
    iconPath: "/static/icons/file_type_video.png",
    handle: (item) => {
      videoViewer.value = true;
      videoUrl.value = ["/api/files/" + item.contentUrl.url];
      resendMessage();
    },
  },
  pdf: {
    iconPath: "/static/icons/file_type_pdf.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  word: {
    iconPath: "/static/icons/file_type_word.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  ppt: {
    iconPath: "/static/icons/file_type_ppt.png",
    handle: (item) => {
      pdfViewer.value = true;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    },
  },
  audio: {
    iconPath: "/static/icons/file_type_audio.png",
    handle: (item) => {
      console.log(item);
      videoViewer.value = true;
      videoUrl.value = ['/api/files/' + item.contentUrl.url];
      videoUrl.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    }
    },
  },
  'pdf': {
    iconPath: '/static/icons/file_type_pdf.png',
  excel: {
    iconPath: "/static/icons/file_type_excel.png",
    handle: (item) => {
      console.log(item);
      pdfViewer.value = true;
      pdfFile.value = '/api/files/' + item.contentUrl.url;
      pdfFile.value = "/api/files/" + item.contentUrl.url;
      resendMessage();
    }
    },
  },
};
const searchText = ref('');
const searchSubject = ref('')
const searchContentType = ref('')
const searchText = ref("");
const searchSubject = ref("");
const searchContentType = ref("");
const loading = ref(false);
@@ -170,33 +275,35 @@
const videoViewer = ref(false);
const imageList = ref([]);
const pdfFile = ref('');
const videoUrl = ref('');
const pdfFile = ref("");
const videoUrl = ref("");
const fileList = ref([]);
const subjectList = ref([]);
const contentTypeList = ref([{ name: '视频', value: 'video' },
  { name: '图片', value: 'img' },
  { name: '音频', value: 'audio' },
  { name: 'PDF', value: 'pdf' },
  { name: 'EXCEL', value: 'excel' },
  { name: 'WORD', value: 'word' },
  { name: 'PPT', value: 'ppt' }]);
const contentTypeList = ref([
  { name: "视频", value: "video" },
  { name: "图片", value: "img" },
  { name: "音频", value: "audio" },
  { name: "PDF", value: "pdf" },
  { name: "EXCEL", value: "excel" },
  { name: "WORD", value: "word" },
  { name: "PPT", value: "ppt" },
]);
const currentIndex = ref(1);
const fileUrl = ref("");
const pageSize = ref(10);
const total = ref(0);
// const fileUrl = ref("");
const fileViewer = ref(false);
const checkRow = (item) => {
    fileUrl.value = item.contentUrl.url;
  // fileUrl.value = item.contentUrl.url;
  fileType[item.contentType] && fileType[item.contentType].handle(item);
  fileViewer.value = true
};
const handleClose = () => {
  fileViewer.value = false;
  fileUrl.value = "";
  console.log("我是否关闭:",fileUrl.value);
};
// const handleClose = () => {
//   fileViewer.value = false;
//   fileUrl.value = "";
//   console.log("我是否关闭:", fileUrl.value);
// };
const closeViewer = () => {
  pdfViewer.value = false;
@@ -207,32 +314,43 @@
const getData = () => {
  loading.value = true;
  getFileList({introduction: searchText.value, subjectId: searchSubject.value, contentType:searchContentType.value}).then(res => {
    loading.value = false;
    fileList.value = res.data;
  }).catch(() => {
    loading.value = false;
  });
  getFileList({
    introduction: searchText.value,
    subjectId: searchSubject.value,
    contentType: searchContentType.value,
    pageSize: pageSize.value,
    pageNum: currentIndex.value,
  })
    .then((res) => {
      loading.value = false;
      fileList.value = res.data;
      total.value = res.total;
    })
    .catch(() => {
      loading.value = false;
    });
};
getData();
const getSubject = () => {
  loading.value = true;
  getSubjectList().then(res => {
    loading.value = false;
    subjectList.value = res.data;
  }).catch(() => {
    loading.value = false;
  });
  getSubjectList()
    .then((res) => {
      loading.value = false;
      subjectList.value = res.data;
    })
    .catch(() => {
      loading.value = false;
    });
};
getSubject();
const resendMessage = () => {
  if (time.value) {
    clearInterval(time.value);
  }
  sendMessage({id: userInfo.value.id, command: 'recordStudyTime'});
  sendMessage({ id: userInfo.value.id, command: "recordStudyTime" });
  time.value = setInterval(() => {
    sendMessage({id: userInfo.value.id, command: 'recordStudyTime'});
    sendMessage({ id: userInfo.value.id, command: "recordStudyTime" });
  }, 5000);
};
@@ -241,15 +359,23 @@
    return fileType[type].iconPath;
  }
};
const handleCurrentChange = (val) => {
const handleSizeChange = (val) => {
  currentIndex.value = 1;
  pageSize.value = val;
  getData();
}
};
const handleCurrentChange = (val) => {
  currentIndex.value = val;
  getData();
};
const searchFile = () => {
  getData();
}
};
//下载
const download = (row) => {
  window.open(row.visitUrl, '_blank');
};
// -----------------------------------生命周期
onMounted(() => {
src/views/personal-center/index.vue
@@ -40,7 +40,7 @@
                    {{ userData.className.join(",") }}
                  </el-form-item>
                  <el-form-item label="注册时间">
                    {{ timestampToDate(userData.createTime) }}
                    {{ userData.createTime }}
                  </el-form-item>
                </el-form>
              </div>
@@ -56,9 +56,10 @@
                  label-width="auto"
                  style="max-width: 600px"
                  :rules="informationRules"
                  ref="informationFormRef"
                >
                  <el-form-item label="真实姓名" prop="name">
                    <el-input v-model="informationForm.name" />
                  <el-form-item label="真实姓名" prop="realName">
                    <el-input v-model="informationForm.realName" />
                  </el-form-item>
                  <el-form-item label="年龄">
                    <el-input v-model="informationForm.age" />
@@ -77,14 +78,19 @@
                      v-model="informationForm.birthDay"
                      type="date"
                      placeholder="Pick a day"
                      :size="size"
                    />
                  </el-form-item>
                  <el-form-item label="手机" prop="phone">
                    <el-input v-model="informationForm.phone" />
                  </el-form-item>
                  <el-form-item>
                    <el-button type="primary" @click="onSubmit">更新</el-button>
                    <div class="submit-box">
                      <el-button
                        type="primary"
                        @click="informationSubmit(informationFormRef)"
                        >更新</el-button
                      >
                    </div>
                  </el-form-item></el-form
                ></el-tab-pane
              >
@@ -93,15 +99,38 @@
                  :model="passwordForm"
                  label-width="auto"
                  style="max-width: 600px"
                  :rules="passwordRules"
                  ref="passwordFormRef"
                >
                  <el-form-item label="旧密码">
                    <el-input v-model="passwordForm.name" />
                  <el-form-item label="旧密码" prop="oldPassword">
                    <el-input
                      v-model="passwordForm.oldPassword"
                      type="password"
                      show-password
                    />
                  </el-form-item>
                  <el-form-item label="新密码">
                    <el-input v-model="passwordForm.name" />
                  <el-form-item label="新密码" prop="newPassword">
                    <el-input
                      v-model="passwordForm.newPassword"
                      type="password"
                      show-password
                    />
                  </el-form-item>
                  <el-form-item label="确认密码">
                    <el-input v-model="passwordForm.name" />
                  <el-form-item label="确认密码" prop="newPasswordA">
                    <el-input
                      v-model="passwordForm.newPasswordA"
                      type="password"
                      show-password
                    />
                  </el-form-item>
                  <el-form-item>
                    <div class="submit-box">
                      <el-button
                        type="primary"
                        @click="passwordSubmit(passwordFormRef)"
                        >保存</el-button
                      >
                    </div>
                  </el-form-item>
                </el-form>
              </el-tab-pane>
@@ -115,17 +144,24 @@
<script setup>
import { ref } from "vue";
import { uploadImg } from "@/api/modules/personalCenter.js";
import { uploadImg, userUpdate,passwordUpdate } from "@/api/modules/personalCenter.js";
import { ElMessage } from "element-plus";
const activeName = ref("information");
const userData = ref(JSON.parse(localStorage.getItem("user")).userInfo);
const informationFormRef = ref();
const passwordFormRef = ref();
const informationForm = ref({
  name: userData.value.realName,
  realName: userData.value.realName,
  sex: userData.value.sex,
  age: userData.value.age,
  phone: userData.value.phone,
  birthDay: userData.value.birthDay,
});
const passwordForm = ref({
  oldPassword: "",
  newPassword: "",
  newPasswordA: "",
});
// 手机号验证逻辑
const validatePhone = (rule, value, callback) => {
@@ -136,15 +172,45 @@
    callback();
  }
};
const validatePassword = (rule, value, callback) => {
  if (!/[A-Z]/.test(value)) {
    callback(new Error("密码必须包含至少一个大写字母"));
  } else if (!/[a-z]/.test(value)) {
    callback(new Error("密码必须包含至少一个小写字母"));
  } else if (!/[0-9]/.test(value)) {
    callback(new Error("密码必须包含至少一个数字"));
  } else {
    callback();
  }
};
const validatePasswordA = (rule, value, callback) => {
  if (value !== passwordForm.value.newPassword) {
    callback(new Error("两次输入密码不同!"));
  } else {
    callback();
  }
};
const informationRules = {
  name: [{ required: true, message: "请填写真实姓名", trigger: "blur" }],
  realName: [{ required: true, message: "请填写真实姓名", trigger: "blur" }],
  phone: [
    { validator: validatePhone, trigger: "blur" },
    { required: true, message: "请输入手机号", trigger: "blur" },
  ],
};
const passwordForm = ref({ name: "" });
const passwordRules = {
  oldPassword: [
    { validator: validatePassword, trigger: "blur" },
    { required: true, message: "请输入旧密码", trigger: "blur" },
  ],
  newPassword: [
    { validator: validatePasswordA, trigger: "blur" },
    { required: true, message: "请输入新密码", trigger: "blur" },
  ],
  newPasswordA: [
    { validator: validatePasswordA, trigger: "blur" },
    { required: true, message: "请输入再次输入新密码", trigger: "blur" },
  ],
};
//头像上传
let formData = new FormData();
const uploadImage = () => {
@@ -179,10 +245,73 @@
    );
  }
};
const informationSubmit = async (formEl) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      informationForm.value.birthDay = timestampToDate(
        informationForm.value.birthDay
      );
      userUpdate(informationForm.value).then(
        () => {
          ElMessage({
            showClose: true,
            message: "更新成功",
            type: "success",
          });
          const newData = JSON.parse(localStorage.getItem("user"));
          newData.userInfo.realName = informationForm.value.realName;
          newData.userInfo.sex = informationForm.value.sex;
          newData.userInfo.age = informationForm.value.age;
          newData.userInfo.phone = informationForm.value.phone;
          newData.userInfo.birthDay = informationForm.value.birthDay;
          localStorage.setItem("user", JSON.stringify(newData));
        },
        (err) => {
          ElMessage.error(err.data.errorMsg);
        }
      );
    } else {
      console.log("error submit!", fields);
    }
  });
};
const passwordSubmit = async (formEl) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      let data = {
        userId:userData.value.id,
        newPassword:passwordForm.value.newPassword,
        oldPassword:passwordForm.value.oldPassword,
      }
      passwordUpdate(data).then(
        () => {
          ElMessage({
            showClose: true,
            message: "修改成功",
            type: "success",
          });
        },
        (err) => {
          ElMessage.error(err.data.errorMsg);
        }
      );
    } else {
      console.log("error submit!", fields);
    }
  });
};
function timestampToDate(timestamp) {
  const date = new Date(timestamp); // 将时间戳转换为Date对象
  const options = { year: "numeric", month: "long", day: "numeric" }; // 定义日期格式
  return new Intl.DateTimeFormat("zh-CN", options).format(date); // 使用Intl.DateTimeFormat进行格式化
  const year = date.getFullYear();
  const month = date.getMonth() + 1; // 月份从0开始,所以要加1
  const day = date.getDate();
  const hours = date.getHours();
  const minutes = date.getMinutes();
  const seconds = date.getSeconds();
  const convertedTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  return convertedTime; // 使用Intl.DateTimeFormat进行格式化
}
</script>
@@ -213,4 +342,10 @@
  overflow: hidden;
  object-fit: cover;
}
.submit-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}
</style>