ruhuxu 5 месяцев назад
Родитель
Сommit
90656161d0
76 измененных файлов с 15194 добавлено и 62 удалено
  1. 6842 0
      alf/base.css
  2. 814 0
      alf/input.jsp
  3. 5832 0
      alf/ss-components.js
  4. 2 0
      api/bzrdm.js
  5. 1 0
      api/xuncha.js
  6. 177 0
      components/SsOnoffButton/index.vue
  7. 2 2
      components/SsSelect/index.vue
  8. 6 0
      pages.json
  9. 1 1
      pages/index/index.vue
  10. 323 0
      pages/kqjl/components/SeatLayout.vue
  11. 284 0
      pages/kqjl/components/StudentCard.vue
  12. 563 3
      pages/kqjl/kqjl_bzrDm.vue
  13. 248 0
      pages/kqjl/kqjl_bzrDm_list.vue
  14. 3 36
      pages/xfjl/index.vue
  15. 0 1
      pages/xuncha/mp_excelRcXcdjl_edit.vue
  16. 15 0
      static/css/main.scss
  17. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin-devtools/components/Td/index.js.map
  18. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin-devtools/pages/kqjl/kqjl_bzrDm.js.map
  19. 1 1
      unpackage/dist/dev/.sourcemap/mp-weixin/api/xuncha.js.map
  20. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map
  21. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/components/SsOnoffButton/index.js.map
  22. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/components/SsSelect/index.js.map
  23. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map
  24. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/components/SeatLayout.js.map
  25. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/components/StudentCard.js.map
  26. 0 1
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/kqjl_bzrDm.js.map
  27. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/kqjl_bzrDm_list.js.map
  28. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/xfjl/index.js.map
  29. 0 0
      unpackage/dist/dev/.sourcemap/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.js.map
  30. 1 1
      unpackage/dist/dev/mp-weixin/app.js
  31. 1 0
      unpackage/dist/dev/mp-weixin/app.json
  32. 0 0
      unpackage/dist/dev/mp-weixin/app.wxss
  33. 0 0
      unpackage/dist/dev/mp-weixin/common/vendor.js
  34. 1 1
      unpackage/dist/dev/mp-weixin/components/Form/index.wxss
  35. 1 1
      unpackage/dist/dev/mp-weixin/components/SsBottom/index.wxss
  36. 1 1
      unpackage/dist/dev/mp-weixin/components/SsCard/index.wxss
  37. 1 1
      unpackage/dist/dev/mp-weixin/components/SsInput/index.wxss
  38. 2 0
      unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.js
  39. 4 0
      unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.json
  40. 1 0
      unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.wxml
  41. 0 0
      unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.wxss
  42. 0 0
      unpackage/dist/dev/mp-weixin/components/SsSearchButton/index.wxss
  43. 0 0
      unpackage/dist/dev/mp-weixin/components/SsSelect/index.js
  44. 6 0
      unpackage/dist/dev/mp-weixin/components/SsSelect/index.json
  45. 1 0
      unpackage/dist/dev/mp-weixin/components/SsSelect/index.wxml
  46. 0 0
      unpackage/dist/dev/mp-weixin/components/SsSelect/index.wxss
  47. 1 1
      unpackage/dist/dev/mp-weixin/components/SsTableTitle/index.wxss
  48. 0 1
      unpackage/dist/dev/mp-weixin/components/Td/index.wxss
  49. 1 1
      unpackage/dist/dev/mp-weixin/components/tabbar/index.wxss
  50. 1 1
      unpackage/dist/dev/mp-weixin/node-modules/uview-plus/components/u-th/u-th.wxss
  51. 1 1
      unpackage/dist/dev/mp-weixin/node-modules/uview-plus/components/u-tr/u-tr.wxss
  52. 0 0
      unpackage/dist/dev/mp-weixin/pages/index/index.js
  53. 0 0
      unpackage/dist/dev/mp-weixin/pages/index/index.wxss
  54. 0 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.js
  55. 6 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.json
  56. 1 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.wxml
  57. 0 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.wxss
  58. 2 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.js
  59. 4 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.json
  60. 1 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.wxml
  61. 0 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.wxss
  62. 0 1
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.js
  63. 12 1
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.json
  64. 0 1
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.wxml
  65. 0 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.wxss
  66. 2 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.js
  67. 8 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.json
  68. 1 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.wxml
  69. 0 0
      unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.wxss
  70. 1 1
      unpackage/dist/dev/mp-weixin/pages/my/index.wxss
  71. 1 1
      unpackage/dist/dev/mp-weixin/pages/xfjl/index.js
  72. 1 1
      unpackage/dist/dev/mp-weixin/pages/xfjl/index.wxml
  73. 0 0
      unpackage/dist/dev/mp-weixin/pages/xfjl/index.wxss
  74. 0 0
      unpackage/dist/dev/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.js
  75. 1 1
      unpackage/dist/dev/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.wxss
  76. 15 0
      unpackage/dist/dev/mp-weixin/static/css/main.scss

+ 6842 - 0
alf/base.css

@@ -0,0 +1,6842 @@
+@import url(var.css);
+
+/* 证件照 */
+.id-photo{
+  width: 153px;
+  height: 213px;
+  background: #e8e8e8;
+  background-size: cover;
+  cursor: pointer;
+  position: relative;
+}
+.id-photo::before {
+  content: "\e605";
+  font-size: 100px;
+  font-family: "iconfont";
+  color: #ccc;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  pointer-events: none; 
+  z-index: 1;  /* 确保图标在内容后面 */
+  /* 其他定位属性 */
+}
+/* 生活照 */
+.life-photo{
+  width: 144px;
+  height: 144px;
+  border-radius: 50%;
+  background:#e8e8e8;
+  background-size: contain;
+  cursor: pointer;
+  position: relative;
+}
+.life-photo::before {
+  content: "\e605";
+  font-size: 80px;
+  font-family: "iconfont";
+  color: #ccc;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  pointer-events: none; 
+  z-index: 1;
+}
+.life-photo img{
+  border-radius: 50%;
+}
+/* 图标相关开始 */
+/* 通用icon */
+.common-icon{
+  font-size: 22px;
+  font-family: "iconfont";
+
+}
+.common-icon-add::before{
+  content: "\e60d";
+  color: #999999;
+
+}
+.common-icon-setting::before{
+  content: "\e630";
+  /* color: #999999; */
+}
+/* 减少 */
+.common-icon-reduce::before{
+  content: "\e6a2";
+  color: #EB6100;
+}
+/* 附件 */
+.common-icon-paper-clip::before{
+  content: "\e676";
+  color: #999999;
+}
+.common-icon-change::before{
+  font-size: 16px;
+  content: "→";
+  color: red;
+}
+/* 表情 */
+.common-icon-smile::before{
+  content: "\e616";
+  color: #999999;
+}
+/* 常用语 */
+.common-icon-common-words::before{
+  content: "\e69d";
+  color: #999999;
+}
+/* 手写 */
+.common-icon-handwriting::before{
+  content: "\e6ab";
+  color: #999999;
+}
+/* 视频播放 */
+.common-icon-video::before{
+  content: "\e699";
+  color: #999999;
+}
+/* 文件夹-关闭 */
+.common-icon-folder-close::before{
+  content: "\e60b";
+  color: #999999;
+}
+/* 文件夹-打开 */
+.common-icon-folder-open::before{
+  content: "\e60c";
+  color: #999999;
+}
+/* 文件 */
+.common-icon-file::before{
+  content: "\e69e";
+  color: #999999;
+}
+/* 刷新 */
+.common-icon-refresh::before{
+  content: "\e635";
+  color: #999;
+}
+/* 待办 */ 
+.common-icon-todo::before{
+  content: "\e65c";
+  color: #999;
+}
+/* 催办 */
+.common-icon-urge::before{
+  content: "\e664";
+  color: #999;
+}
+/* 快捷发起 */
+.common-icon-quick-start::before{
+  content: "\e6a6";
+  color: #999;
+}
+/* 公告 */
+.common-icon-notice::before{
+  content: "\e6ac";
+  color: #999;
+}
+/* 统计图 */
+.common-icon-chart::before{
+  content: "\e6a5";
+  color: #999;
+}
+/* 请假 */
+.common-icon-leave-big::before{
+  font-size: 36px;
+  content: "\e6af";
+  color: #999999;
+}
+/* 收付款 */
+.common-icon-receipt-big::before{
+  font-size: 36px;
+  content: "\e68e";
+  color: #999999;
+}
+/* 考勤 */
+.common-icon-attendance-big::before{
+  font-size: 36px;
+  content: "\e694";
+  color: #999999;
+}
+/* 会议 */
+.common-icon-meeting::before{
+  content: "\e692";
+  color: #999999;
+}
+/* 一卡通 */
+.common-icon-card::before{
+  content: "\e6a0";
+  color: #999999;
+}
+/* 个人网站 */
+.common-icon-site::before{
+  content: "\e6ae";
+  color: #999999;
+}
+.common-icon-arrow-right{
+  font-size: 14px;
+}
+.common-icon-arrow-right::before{
+  content: "\e640";
+}
+/* 通用icon结束 */
+/* 全局左侧导航开始 */
+.nav-icon {
+  font-size: 22px;
+  font-family: "iconfont";
+  padding: 10px;
+  color: #565d6d;
+}
+.nav-icon-home::before {
+  content: "\e690";
+}
+.nav-icon-person::before {
+  content: "\e605";
+}
+.nav-icon-knowledge::before {
+  content: "\e62c";
+}
+.nav-icon-statistics::before {
+  content: "\e68a";
+}
+.nav-icon-category::before {
+  content: "\e652";
+}
+.nav-icon-add::before {
+  content: "\e60d";
+}
+.nav-icon-search::before {
+  content: "\e62f";
+}
+.nav-icon-folder-close::before{
+  content: "\e60b";
+  font-size: 19px;
+}
+.nav-icon-folder-open::before{
+  content: "\e60c";
+  font-size: 19px;
+}
+/* 岗位 */
+.nav-icon-post::before{
+  content: "\e69c";
+}
+/* 单位 */
+.nav-icon-unit::before{
+  content: "\e662";
+}
+/* 全局左侧导航结束 */
+/* 顶部导航开始 */
+.header-icon {
+  /* 基础样式 */
+  width: 36px;
+  height: 36px;
+  font-size: 22px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-family: "iconfont";
+  border-radius: 4px;
+  border: 1px solid var(--icon-item-border-color, transparent);
+}
+
+.header-icon:hover {
+  --icon-item-border-color: #edf1f5;
+}
+
+.header-help::after {
+  content: "\e6a7";
+  /* 帮助图标 */
+}
+
+.header-setting::after {
+  content: "\e60e";
+  /* 设置图标 */
+}
+
+.header-save::after {
+  content: "\e68d";
+  /* 设置图标 */
+}
+
+.header-menu::after {
+  content: "\e6ad";
+  /* 菜单图标 */
+}
+
+.header-home::after {
+  content: "\e600";
+  /* 主页图标 */
+}
+.header-skin::after {
+  content: "\e689";
+  /* 换肤图标 */
+}
+
+.header-lock::after {
+  content: "\e69f";
+  /* 锁定图标 */
+}
+
+.header-logout {
+  width: 48px;
+  height: 48px;
+  font-size: 33px;
+}
+
+.header-logout:hover {
+  background-color: #000;
+}
+
+.header-logout::after {
+  content: "\e6a1";
+  /* 退出图标 */
+}
+
+/* 顶部导航结束 */
+/* 全局菜单图标开始 */
+.global-menu-icon {
+  font-size: 16px;
+  font-family: "iconfont";
+  /* padding: 10px; */
+}
+/* 全局菜单图标结束 */
+/* 全局查询列表卡片 */
+.cart-list-icon {
+  font-size: 22px;
+  font-family: "iconfont";
+  /* padding: 10px; */
+}
+.cart-list-setting::before {
+  content: "\e630";
+  color: #dddddd;
+}
+
+/* 弹窗底部按钮icon */
+.bottom-div-icon{
+  font-size: 20px;
+  font-family: "iconfont";
+}
+.bottom-div-save::before{
+  content: "\e68d";
+}
+.bottom-div-close{
+  display: flex;
+  align-items: center;
+}
+.bottom-div-close::before{
+  content: "\e693";
+  font-size: 16px;
+}
+.bottom-div-back::before{
+  content: "\e638";
+}
+/* 表单组件icon开始 */
+.form-icon{
+  font-size: 18px;
+  font-family: "iconfont";
+}
+
+.form-icon-select::before{
+  content: "\e63e";
+}
+.form-icon-transform-select::before{
+  content: "\e63f";
+}
+.form-icon-select-checked::before{
+  content: "\e68d";
+}
+
+.form-icon-onoffbutton-checked::before{
+  content: "\e62d";
+}
+.form-icon-onoffbutton-unchecked::before{
+  content: "\e62b";
+}
+.form-icon-time::before{
+  content: "\e606";
+}
+.form-icon-prev-month::before{
+  content: "\e641";
+}
+.form-icon-prev-year::before{
+  content: "\e6b1";
+}
+.form-icon-next-month::before{
+  content: "\e640";
+}
+.form-icon-next-year::before{
+  content: "\e6b2";
+}
+/* 表单组件icon结束 */
+/* 登录页icon开始 */
+.login-icon{
+  font-size: 22px;
+  font-family: "iconfont";
+}
+.login-icon-user::before{
+  content: "\e605";
+}
+.login-icon-password::before{
+  content: "\e607";
+}
+.login-icon-check-code::before{
+  content: "\e608";
+}
+.login-icon-time::before{
+  content: "\e606";
+}
+.login-icon-loginin::before{
+  content: "\e6a1";
+}
+.login-icon-yaoyiyao::before{
+  content: "\e60f";
+}
+.login-icon-change-user{
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 22px !important;
+  height: 22px;
+  margin-right: 5px;
+  margin-top: 5px;
+  cursor: pointer;
+}
+.login-icon-change-user::before{
+  content: "\e609";
+}
+/* 登录页icon结束 */
+/* 弹窗icon开始 */
+.dialog-icon{
+  font-size: 22px;
+  font-family: "iconfont";
+}
+/* 关闭 */
+.dialog-icon-close::before{
+  content: "\e693";
+  font-size: 28px;
+}
+/* 下载 */
+.dialog-icon-download::before{
+  content: "\e691";
+}
+/* 打印 */
+.dialog-icon-print::before{
+  content: "\e66f";
+}
+/* 设置 */
+.dialog-icon-setting::before{
+  content: "\e630";
+}
+/* 收藏 */
+.dialog-icon-collect::before{
+  content: "\e698";
+}
+/* 帮助 */
+.dialog-icon-help::before{
+  content: "\e6cd";
+}
+/* 全屏 */
+.dialog-icon-full-screen::before{
+  content: "\e6ca";
+}
+/* 锁屏 */
+.dialog-icon-lock::before{
+  content: "\e697";
+}
+
+/* editor相关图标开始 */
+.editor-icon{
+  font-size: 16px;
+  font-family: "iconfont";
+  color: #666666;
+}
+/* 加粗 */
+.editor-icon-bold::before{
+  content: "\e68b";
+}
+/* 斜体 */
+.editor-icon-italic::before{
+  content: "\e66b";
+}
+/* 下划线 */
+.editor-icon-underline::before{
+  content: "\e685";
+}
+/* 删除线 */
+.editor-icon-strikethrough::before{
+  content: "\e66e";
+}
+
+/* 加粗 */
+.editor-icon-bold::before{
+  content: "\e68b";
+}
+/* 斜体 */
+.editor-icon-italic::before{
+  content: "\e66b";
+}
+/* 下划线 */
+.editor-icon-underline::before{
+  content: "\e685";
+}
+/* 删除线 */
+.editor-icon-strikethrough::before{
+  content: "\e66e";
+}
+
+/* 清除格式 */
+.editor-icon-eraser::before{
+  content: "\e6c2";
+}
+/* 复制格式 */
+.editor-icon-copyformat::before{
+  content: "\e68b";
+}
+/* 字体 */
+.editor-icon-font::before{
+  content: "\e680";
+}
+/* 字号 */
+.editor-icon-fontsize::before{
+  content: "\e67d";
+}
+/* 文字颜色 */
+.editor-icon-brush::before{
+  content: "\e681";
+}
+/* 段落 */
+.editor-icon-paragraph::before{
+  content: "\e682";
+}
+/* 左对齐 */
+.editor-icon-align-left::before{
+  content: "\e67e";
+}
+/* 居中对齐 */
+.editor-icon-align-center::before{
+  content: "\e67b";
+}
+/* 右对齐 */
+.editor-icon-align-right::before{
+  content: "\e67f";
+}
+/* 两端对齐 */
+.editor-icon-align-justify::before{
+  content: "\e67c";
+}
+/* 无序列表 */
+.editor-icon-ul::before{
+  content: "\e6c3";
+}
+/* 有序列表 */
+.editor-icon-ol::before{
+  content: "\e6c7";
+}
+/* 增加缩进 */
+.editor-icon-indent::before{
+  content: "\e6c8";
+}
+/* 减少缩进 */
+.editor-icon-outdent::before{
+  content: "\e6c9";
+}
+/* 图片 */
+.editor-icon-image::before{
+  content: "\e683";
+}
+/* 文件 */
+.editor-icon-file::before{
+  content: "\e668";
+}
+/* 视频 */
+.editor-icon-video::before{
+  content: "\e699";
+}
+/* 表格 */
+.editor-icon-table::before{
+  content: "\e677";
+}
+/* 链接 */
+.editor-icon-link::before{
+  content: "\e676";
+}
+/* 源代码 */
+.editor-icon-source::before{
+  content: "\e68b";
+}
+/* 预览 */
+.editor-icon-preview::before{
+  content: "\e642";
+}
+/* 全屏 */
+.editor-icon-fullsize::before{
+  content: "\e6c4";
+}
+/* 退出全屏 */
+.editor-icon-fullsize-exit::before{
+  content: "\e6cb";
+}
+/* 打印 */
+.editor-icon-print::before{
+  content: "\e66f";
+}
+/* 撤销 */
+.editor-icon-undo::before{
+  content: "\e688";
+}
+/* 重做 */
+.editor-icon-redo::before{
+  content: "\e686";
+}
+/* 查找 */
+.editor-icon-find::before{
+  content: "\e62f";
+}
+/* 全选 */
+.editor-icon-selectall::before{
+  content: "\e68b";
+}
+/* 隐藏原有的 SVG */
+.jodit-toolbar-button__trigger svg {
+  display: none;
+}
+
+/* 添加我们自己的图标 */
+.jodit-toolbar-button__trigger::after {
+  content: "\e63e";  
+  font-family: "iconfont" !important; 
+  font-size: 12px;
+}
+.jodit-toolbar-button_with-trigger_true{
+  margin-right: 4px !important;
+}
+.jodit-toolbar-button_with-trigger_true>.jodit-toolbar-button__button{
+  width: 20px !important;
+  min-width: 20px !important;
+}
+/* editor相关图标结束 */
+/* 弹窗icon结束 */
+/* 图标相关结束 */
+.self-block {
+  width: 100%;
+  height: 100%;
+}
+
+body * {
+  box-sizing: border-box;
+}
+
+html,
+body {
+  margin: 0;
+  padding: 0;
+}
+
+html,
+body,
+#app {
+  width: 100%;
+  height: 100%;
+  /* min-width: 1024px; */
+}
+
+i{
+  font-style: normal;
+}
+
+input::placeholder ,textarea::placeholder{
+  color: #999;
+}
+
+/*定义滚动条高宽及背景
+ 高宽分别对应横竖滚动条的尺寸*/
+::-webkit-scrollbar {
+  width: 8px;
+  /* background-color: #F5F5F5; */
+  border-radius: 4px;
+  margin: 0 6px;
+}
+
+/*定义滚动条轨道
+  内阴影+圆角*/
+::-webkit-scrollbar-track {
+  border-radius: 4px;
+  background-color: #F5F5F5;
+}
+
+/*定义滑块
+  内阴影+圆角*/
+::-webkit-scrollbar-thumb {
+  border-radius: 4px;
+  background-color: #c1c1c1;
+}
+
+
+/* 页面布局 */
+.layout-container {
+  --header-height: 70px;
+  --left-side-width: 60px;
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow: hidden;
+}
+
+.layout-container .header {
+  height: var(--header-height);
+  width: 100%;
+  box-sizing: border-box;
+}
+
+.layout-container .content-area {
+  width: 100%;
+  height: calc(100% - var(--header-height));
+  padding-right: 6px;
+}
+
+.layout-container .content-area:after {
+  content: "";
+  display: block;
+  width: 0;
+  height: 0;
+  clear: both;
+}
+
+.layout-container .left-side {
+  float: left;
+  height: 100%;
+  width: var(--left-side-width);
+  position: relative;
+}
+
+.layout-container .left-side-container {
+  --left-size-width: 100%;
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: var(--left-size-width);
+  transition: width 0.2s;
+}
+
+.layout-container .left-side-container[size="max"] {
+  --left-size-width: 230px;
+}
+
+.layout-container .btn-size {
+  position: absolute;
+  bottom: 0;
+  left: calc(100% + 1px);
+  width: 16px;
+  height: 18px;
+  background: #fff;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  z-index: 100;
+  --border-color: #dddfe6;
+  border-bottom: 1px solid var(--border-color);
+  border-right: 1px solid var(--border-color);
+}
+
+.layout-container .btn-size::before {
+  content: "";
+  position: absolute;
+  left: -7px;
+  top: -22px;
+  width: 22px;
+  height: 22px;
+  background: #fff;
+  transform-origin: 100% 100%;
+  transform: rotate(-45deg);
+  z-index: 1;
+  border-right: 1px solid var(--border-color);
+}
+
+.layout-container .btn-size .icon-container {
+  position: absolute;
+  z-index: 2;
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  padding: 0 0 1px 1px;
+}
+
+.layout-container .left-side-content {
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 100;
+  overflow: hidden;
+  background: #fafbfe;
+  
+  /* display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  align-items: center; */
+
+}
+
+.layout-container .left-side-content:hover {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.layout-container .left-side-content:after {
+  content: "";
+  height: 100%;
+  width: 1px;
+  position: absolute;
+  left: 100%;
+  top: 0;
+  background: #dadee2;
+  box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.24);
+}
+
+.layout-container  .main-content {
+  float: right;
+  height: 100%;
+  width: calc(100% - var(--left-side-width));
+}
+
+.layout-container[sys-mode="edit"] {
+  --edit-box-tools-display: block;
+}
+
+.layout-container[sys-mode="edit"] .can-resize-box:hover {
+  --block-title-visible: hidden;
+}
+
+.flex-start-center {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.flex-between-center {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+/* 公共头部区域开始 */
+.global-header-container {
+  background: var(--lightdark);
+  color: var(--white);
+  height: 100%
+}
+
+.global-header-container>div {
+  height: 100%;
+}
+
+.global-header-container .logo {
+  height: 100%;
+  width: 183px;
+  cursor: pointer;
+  position: relative;
+  z-index: 200;
+}
+
+.global-header-container .logo::after {
+  position: absolute;
+  content: "";
+  width: 0;
+  height: 50%;
+  top: calc(50% - 50% / 2);
+  right: 0;
+  border-right: 1px solid var(--lightdark-sub);
+}
+
+.global-header-container .logo:hover {
+  --header-menu-visible: visible;
+}
+
+.global-header-container .logo .img {
+  padding: 12px 30px 12px calc(var(--space-size) / 2);
+  height: 100%;
+  width: 100%;
+}
+
+.global-header-container .img img {
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+}
+
+.global-header-container .menu {
+  visibility: var(--header-menu-visible, hidden);
+  transition: top 0.3s;
+  font-size: 14px;
+  color: #333;
+  top: 100%;
+  left: 0;
+  position: absolute;
+  /* width: 100%; */
+  background: #393d51;
+  border-top: 1px solid #dddfe6;
+  padding: 10px 2px;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+
+.global-header-container .menu>div {
+  height: 36px;
+  color: var(--header-menu-color, #fff);
+  background: var(--header-menu-bg, transparent);
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  padding-left: 8px;
+  padding-right: 8px;
+  gap: 10px;
+  white-space: nowrap;
+}
+
+.global-header-container .menu>div:hover {
+  --header-menu-color: #333;
+  --header-menu-bg: #fffdfd;
+}
+
+.global-header-container .bread-crumb {
+  padding-left: 30px;
+  padding-top: 30px;
+  font-size: 18px;
+  color: var(--white);
+}
+
+.global-header-container.bread-crumb .content {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.global-header-container.bread-crumb .home-icon {
+  margin-right: calc(var(--space-size) / 2);
+  margin-top: -2px;
+}
+
+.global-header-container.bread-crumb .split-icon {
+  margin: 0 var(--space-size);
+}
+
+.global-header-container.bread-crumb .content a {
+  color: inherit;
+  text-decoration: none;
+}
+
+.global-header-container .menu-area {
+  padding-top: 10px;
+  padding-right: var(--space-size);
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  gap: 12px;
+}
+
+.global-header-container .search-area {
+  padding: 0 1em;
+  width: 350px;
+  height: 40px;
+}
+
+
+/* 顶部菜单全局搜索框 */
+.search-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  border: none;
+  border-radius: 5px;
+  overflow: hidden;
+  --search-input-font-size: 16px;
+  --search-bg: var(--white, #fff);
+  --search-color: var(--dark, #252835);
+  --input-placeholder-color: #666;
+  background: var(--search-bg);
+  color: var(--search-color);
+}
+
+.search-container.dark {
+  --search-bg: var(--dark, #252835);
+  --search-color: var(--white, #fff);
+  --input-placeholder-color: #9c9fa7;
+}
+
+.search-container input {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  z-index: 1;
+  color: inherit;
+  padding: 0 1em;
+  border: unset;
+  font-size: var(--search-input-font-size);
+  background: unset;
+}
+
+.search-container input:disabled {
+  cursor: pointer;
+}
+
+.search-container input:focus {
+  outline: unset;
+}
+
+.search-container input::-moz-placeholder {
+  color: var(--input-placeholder-color, #666);
+}
+
+.search-container input::placeholder {
+  color: var(--input-placeholder-color, #666);
+}
+
+.search-container .icon-container {
+  right: 15px;
+  top: 50%;
+  transform: translateY(-50%);
+  position: absolute;
+  z-index: 2;
+  pointer-events: none;
+  padding-left: 10px;
+  background: var(--search-bg);
+}
+
+/* 公共头部区域结束 */
+
+/* 全局左部边框开始 */
+.left-side-container {
+  width: 100%;
+  height: 100%;
+  padding: 0;
+  background: #fafbfe;
+  /* overflow-y: auto;
+  overflow-x: hidden; */
+}
+/* 菜单项小圆点 */
+.menu-item-dot {
+  width: 5px;
+  height: 5px;
+  border-radius: 50%;
+  background-color: #8e8e8e;
+  position: absolute;
+  right: 5px;
+  /* 调整右侧位置 */
+  bottom: 5px;
+  /* 调整底部位置 */
+  font-size: 16px;
+  /* 调整圆点大小 */
+}
+
+.left-side-container .menu-item {
+  height: 60px;
+  width: 100%;
+  box-sizing: border-box;
+  color: var(--lightdark);
+  cursor: pointer;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.left-side-container .add-menu-btn {
+  display: var(--menu-add-btn-display, none);
+}
+
+.left-side-container .add {
+  width: 45px;
+  height: 45px;
+  border-radius: 5px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  box-shadow: 0 1px 4px #ccc;
+}
+
+.left-side-container .menu-item-content {
+  width: 100%;
+  height: 100%;
+  padding: 0 8px;
+  gap: 5px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  position: relative;
+  --edit-mark-display: none;
+}
+
+.left-side-container .menu-item-content:hover {
+  --edit-mark-display: var(--menu-edit-mark-display, none);
+}
+
+.left-side-container .menu-item-label {
+  height: 1.5em;
+  overflow: hidden;
+  transition: all 0.5s;
+  font-size: 18px;
+  color: #565d6d;
+  opacity: var(--menu-item-label-opacity, 0);
+  visibility: var(--menu-item-label-visible, hidden);
+}
+
+.left-side-container .edit-mark {
+  display: var(--edit-mark-display);
+  right: -1px;
+  top: -1px;
+  position: absolute;
+  color: #c3c6ca;
+}
+
+.left-side-container .edit-mark:hover {
+  color: #333;
+}
+
+.left-side-container .menu-item-content:hover {
+  background: #edf1f5;
+}
+
+.left-side-container .menu-item-content:hover.edit .mark {
+  display: block;
+}
+
+.left-side-container .icon-container {
+  position: relative;
+  padding: 10px;
+  box-sizing: content-box;
+  width: 24px;
+  height: 24px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  flex-shrink: 0;
+}
+.left-side-container .active{
+  background: #edf1f5;
+}
+/* 全局左部边框结束 */
+
+/* 一级页面搜索开始 */
+.search-bar-contaienr {
+  height: 100%;
+  width: 100%;
+  padding: 0 20px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  gap: 20px;
+  --col-lg-3: 270px;
+  position: relative;
+
+}
+
+.search-bar-contaienr input {
+  padding: 8px 10px;
+  margin: 0;
+  outline: unset;
+  border: 1px solid #c4c7cc;
+  border-radius: 3px;
+  font-size: 14px;
+}
+
+
+
+.search-bar-contaienr button {
+  font-size: 14px;
+  outline: unset;
+  border: unset;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  /* gap: 5px; */
+  padding: 8px 20px;
+  border-radius: 3px;
+  margin: 0;
+  cursor: pointer;
+  border: 1px solid #c4c7cc;
+}
+
+.search-bar-contaienr button:hover {
+  background: #393d51;
+  border: 1px solid #393d51;
+  color: #fff;
+}
+
+.search-bar-contaienr .add {
+  position: relative;
+}
+
+.search-bar-contaienr .popup {
+  position: absolute;
+  top: calc(100% + 15px);
+  right: 0;
+  width: 100%;
+  height: 130px;
+  background-color: #393d51;
+  border-radius: 5px;
+  padding: 10px 0;
+  z-index: 10;
+}
+
+.search-bar-contaienr .popup::after {
+  content: "";
+  width: 1em;
+  height: 1em;
+  background: #393d51;
+  position: absolute;
+  right: 1.5em;
+  top: -0.5em;
+  transform: rotate(45deg);
+}
+.search-bar-contaienr .popup >div {
+  border-bottom: 1px solid #303445;
+}
+.search-bar-contaienr .popup >div:last-child {
+  border-bottom: unset;
+}
+
+.search-bar-contaienr button.add>div.popup>div {
+  color: #d8d8d8;
+  font-size: 14px;
+  padding: 8px 20px;
+  cursor: pointer;
+}
+
+.search-bar-contaienr button.add>div.popup>div:not(:last-child) {
+  border-bottom: 1px solid #303445;
+}
+
+.search-bar-contaienr button.add>div.popup>div:hover {
+  background: #fffdfd;
+  color: #333;
+}
+
+
+.search-bar-contaienr>div {
+  height: 32px;
+}
+
+.search-bar-contaienr>.input {
+  border: 1px solid #c4c7cc;
+  border-radius: 3px;
+  font-size: 14px;
+}
+
+.search-bar-contaienr>div.input>input {
+  height: 100%;
+  width: 100%;
+  padding: 8px 10px;
+  margin: 0;
+  outline: unset;
+  border: unset;
+  border-radius: inherit;
+  background: unset;
+  font-size: inherit;
+}
+
+
+
+.search-bar-contaienr button {
+  height: 32px;
+  font-size: 14px;
+  outline: unset;
+  border: unset;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  /* gap: 5px; */
+  padding: 0 20px;
+  border-radius: 3px;
+  margin: 0;
+  cursor: pointer;
+  background: var(--btn-bg, unset);
+  color: var(--btn-color, #999999);
+  border: 1px solid var(--btn-border-color, #c4c7cc);
+}
+
+.search-bar-contaienr button:hover {
+  --btn-bg: #393d51;
+  --btn-color: #fff;
+}
+
+.search-bar-contaienr .input {
+  width: var(--col-lg-3);
+  height: 32px;
+  /* border: 1px solid #c4c7cc; */
+  border-radius: 4px;
+  position: relative;
+}
+
+.search-bar-contaienr .input>input {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 1;
+  outline: unset;
+  border: unset;
+  background: unset;
+  padding: 0 15px;
+  line-height: 32px;
+  font-size: 14px;
+}
+
+.search-bar-contaienr .input>input::-moz-placeholder {
+  color: #999;
+}
+
+.search-bar-contaienr .input>input::placeholder {
+  color: #999;
+}
+
+.search-bar-contaienr .bar {
+  padding: 0 10px;
+  position: absolute;
+  top: 0;
+  right: 0;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  color: #c4c7cc;
+  gap: 12px;
+}
+
+.search-bar-contaienr .bar .icon-container {
+  position: relative;
+  display: block;
+}
+
+.search-bar-contaienr .bar .icon-container:not(:last-child)::after {
+  content: "";
+  position: absolute;
+  top: 50%;
+  left: calc(100% + 12px);
+  transform: translateY(-50%);
+  width: 0;
+  height: 20px;
+  border-right: 1px solid #c4c7cc;
+}
+
+
+
+.search-bar-contaienr button {
+  font-size: 16px;
+  outline: unset;
+  border: unset;
+  color: #999;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  /* gap: 5px; */
+  padding: 0 20px;
+  border-radius: 4px;
+  margin: 0;
+  /* line-height: 2em; */
+  cursor: pointer;
+  background: var(--btn-bg, unset);
+  color: var(--btn-color, #999999);
+  border: 1px solid var(--btn-border-color, #c4c7cc);
+}
+
+.search-bar-contaienr button:hover {
+  --btn-bg: #393d51;
+  --btn-color: #fff;
+}
+.search-bar-contaienr .popup-win.bottom{
+  top: 100% !important;
+}
+.search-bar-contaienr .select-container .suffix>div{
+  width: 30px !important;
+  height: 30px !important;
+}
+/* 一级页面搜索结束 */
+
+/* 知识库卡片开始 */
+.knowledge-item-container {
+  width: 573px;
+  /* height: 220px; */
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  border: 1px solid #dddfe6;
+  --header-display: none;
+  --header-color: #999;
+}
+
+.knowledge-item-container:hover {
+  --header-display: flex;
+  box-shadow: 8px 8px 0px #3a3e513d;
+}
+
+.knowledge-item-container:hover .cart-list-setting{
+  display: block;
+}
+/* .knowledge-item-container:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dddfe6;
+} */
+.knowledge-item-container.active{
+  box-shadow: 8px 8px 0px #3a3e513d;
+}
+.knowledge-item-container.active .header{
+  border-radius: unset;
+}
+/* .knowledge-item-container.active::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #585e6e;
+} */
+
+.knowledge-item-container .active {
+  border: 1px solid #ddd;
+}
+
+.knowledge-item-container .action-bar {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.knowledge-item-container>div.action-bar:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.knowledge-item-container .header {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.knowledge-item-container .header:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+.knowledge-item-container .header:hover .cart-list-setting::before{
+  color: #ffffff;
+}
+.knowledge-item-container .body {
+  padding: 20px 25px;
+}
+
+.knowledge-item-container .box-header>div:first-child {
+  color: #333333;
+  font-size: 20px;
+  line-height: 2em;
+}
+
+.knowledge-item-container .box-body {
+  /* height: 140px; */
+  color: #333;
+  padding: 10px 0;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: flex-end;
+  --right-padding-left: 20px;
+  --right-width: calc(100% - 86px);
+}
+
+.knowledge-item-container .no-thumb {
+  --right-padding-left: 0;
+  --right-width: 100%;
+}
+
+.knowledge-item-container .left {
+  width: 88px !important;
+  height: 121px !important;
+  border: 1px solid #f6f6f6;
+}
+
+.knowledge-item-container .left>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+  display: block;
+}
+
+.knowledge-item-container .right {
+  width: var(--right-width);
+  padding-left: var(--right-padding-left);
+  padding-top: 5px;
+}
+
+.knowledge-item-container .right .title {
+  font-size: 16px;
+  color: #666666;
+  line-height: 2em;
+  /* padding-right: 1em; */
+  line-height: 24px;
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 1;
+  -webkit-box-orient: vertical;
+}
+
+.knowledge-item-container  .desc {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #999999;
+  line-height: 1.8em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  gap: 20px;
+}
+/* 知识库卡片结束 */
+/* 知识库文件夹开始 */
+.ss-folder-list-trapezoid {
+  width: 100px;
+  height: 0;
+  /* border-left: 25px solid transparent; */
+  border-right: 30px solid transparent;
+  border-bottom: 20px solid #fafbfe;
+  border-radius: 4px 0 0 0;
+  position: absolute;
+  top: 0px;
+  left: 0;
+  z-index: 11;
+}
+.ss-folder-list-top-transparent {
+  width: 100%;
+  height: 10px;
+  position: absolute;
+  top: 0;
+  left: 0;
+  background: transparent;
+  border-radius: 4px 4px 0 0;
+  z-index: 1;
+}
+.ss-folder-list-top {
+  width: 100%;
+  height: 10px;
+  position: absolute;
+  top: 10px;
+  left: 0;
+  background: #dcdee5;
+  border-radius: 4px 4px 0 0;
+}
+.ss-folder-list-right {
+  width: 8px;
+  height: calc(100% - 10px);
+  position: absolute;
+  bottom: 0;
+  right: 0px;
+  background: #dcdee5;
+  border-radius: 0 4px 4px 0;
+}
+
+.ss-folder-list {
+  width: 573px;
+  /* height: 220px; */
+  box-shadow: -3px 6px 5px #a1a3a6;
+  background: transparent;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  /* border: 1px solid #dddfe6; */
+  --header-display: none;
+  --header-color: #999;
+}
+
+.ss-folder-list:hover {
+  --header-display: flex;
+  box-shadow: 8px 8px 0px #3a3e513d;
+}
+.ss-folder-list:hover
+  .ss-folder-list-top-transparent {
+  background: #dcdee5;
+  border-radius: unset;
+}
+.ss-folder-list:hover .ss-folder-list-top,
+.ss-folder-list:hover .ss-folder-list-right {
+  border-radius: unset;
+}
+.ss-folder-list:hover .cart-list-setting {
+  display: block;
+}
+/* .ss-folder-list:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dcdee5;
+} */
+.ss-folder-list.active{
+  box-shadow: 8px 8px 0px #3a3e513d;
+}
+.ss-folder-list.active .header {
+  border-radius: unset;
+}
+.ss-folder-list.active
+  .ss-folder-list-top-transparent {
+  background: #585e6e;
+  border-radius: unset;
+}
+/* .ss-folder-list.active::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #585e6e;
+} */
+
+.ss-folder-list .active {
+  border: 1px solid #ddd;
+}
+
+.ss-folder-list .action-bar {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.ss-folder-list > div.action-bar:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.ss-folder-list .header {
+  background-color: #fafbfe;
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 20px;
+  right: 8px;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.ss-folder-list .header:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+.ss-folder-list .header:hover .cart-list-setting::before {
+  color: #ffffff;
+}
+.ss-folder-list .body {
+  margin: 20px 0 0 0;
+  height: calc(100% - 20px);
+  background: #fafbfe;
+}
+
+.ss-folder-list .box-header > div:first-child {
+  color: #333333;
+  font-size: 20px;
+  line-height: 2em;
+}
+.ss-folder-list .box-header,
+.ss-folder-list .box-body {
+  background-color: #fafbfe;
+  padding: 0 25px;
+}
+.ss-folder-list .box-body {
+  /* height: 140px; */
+  color: #333;
+  padding: 10px 25px ;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: flex-end;
+  --right-padding-left: 20px;
+  --right-width: calc(100% - 210px);
+}
+
+.ss-folder-list .no-thumb {
+  --right-padding-left: 0;
+  --right-width: 100%;
+}
+
+.ss-folder-list .left {
+  width: 215px !important;
+  height: 121px !important;
+  border: 1px solid #f6f6f6;
+}
+
+.ss-folder-list .left > img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+  display: block;
+}
+
+.ss-folder-list .right {
+  width: var(--right-width);
+  padding-left: var(--right-padding-left);
+  padding-top: 5px;
+}
+
+.ss-folder-list .right .title {
+  font-size: 16px;
+  color: #666666;
+  line-height: 2em;
+  /* padding-right: 1em; */
+  line-height: 24px;
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 1;
+  -webkit-box-orient: vertical;
+}
+
+.ss-folder-list .desc {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #999999;
+  line-height: 1.8em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  gap: 20px;
+}
+/* 知识库文件夹结束 */
+
+/* 一级页面卡片左右结构开始 */
+.item-container {
+  width: 702px;
+  height: 148px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  --header-display: none;
+  --header-color: #999;
+}
+
+.item-container:hover {
+  --header-display: flex;
+}
+
+.item-container:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dddfe6;
+}
+
+.item-container .active {
+  border: 1px solid #ddd;
+}
+
+.item-container .header {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.item-container .header:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.item-container .body {
+  height: 100%;
+  padding: 12px var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.item-container .left {
+  padding: 10px;
+  width: 150px;
+}
+
+.item-container .right {
+  width: calc(100% - 150px);
+}
+
+.item-container .right .title {
+  font-size: 22px;
+  color: #333;
+  line-height: 2em;
+  padding-right: 1em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.item-container .desc {
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.item-container .progress {
+  margin-top: 5px;
+  background: #edeff0;
+  width: 100%;
+  height: 22px;
+  border-radius: 11px;
+  padding: 0 65px 0 10px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  cursor: pointer;
+}
+
+.item-container .progress:hover {
+  --progress-color: #006cf1;
+}
+
+.item-container  .progress>div {
+  height: 4px;
+  position: relative;
+  border-radius: 2px;
+  background: var(--progress-color, #666666);
+}
+
+.item-container  .progress>div>div {
+  position: absolute;
+  top: 50%;
+  left: calc(100% + 10px);
+  transform: translateY(-50%);
+  font-size: 12px;
+}
+
+.page-container .content-area .left {
+  width: calc(100% - var(--project-detail-width) - 6px);
+  height: 100%;
+  overflow-y: auto;
+  /* margin-right: 6px; */
+}
+
+.page-container .content-area .left .left-content {
+  width: 100%;
+  padding: 10px;
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  gap: 16px;
+  overflow-y: hidden;
+}
+
+/* 一级页面卡片左右结构结束 */
+
+/* 一级页面卡片上下结构开始 */
+.item-container2 {
+  width: 573px;
+  height: 170px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  border: 1px solid #dddfe6;
+  --header-display: none;
+  --header-color: #999;
+}
+
+.item-container2:hover {
+  --header-display: flex;
+}
+
+.item-container2:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dddfe6;
+}
+
+.item-container2 .active {
+  border: 1px solid #ddd;
+}
+
+.item-container2 .header {
+  padding: 10px 60px 2px 20px;
+}
+
+.item-container2 .title {
+  font-size: 22px;
+  color: #333;
+  line-height: 2em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.item-container2 .body {
+  padding: 0 var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.item-container2 .body>div {
+  height: 100px;
+}
+
+.item-container2 .body .left {
+  width: 180px;
+  background: #fafbfe;
+  border: 1px solid #f6f6f6;
+}
+
+.item-container2 .body .left img {
+  width: 100%;
+  height: 100%;
+}
+
+.item-container2 .body .right {
+  width: calc(100% - 180px);
+  padding: 5px 0 0 20px;
+}
+
+.item-container2  .content {
+  height: 60px;
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
+
+.item-container2  .tip {
+  margin-top: 5px;
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.item-container2 .action-bar {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.item-container2 .action-bar:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.item-container2 .progress {
+  margin-top: 5px;
+  background: #edeff0;
+  width: 100%;
+  height: 22px;
+  border-radius: 11px;
+  padding: 0 65px 0 10px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  cursor: pointer;
+}
+
+.item-container2 .progress:hover {
+  --progress-color: #006cf1;
+}
+
+.item-container2 .progress>div {
+  height: 4px;
+  position: relative;
+  border-radius: 2px;
+  background: var(--progress-color, #666666);
+}
+
+.item-container2 .progress>div>div {
+  position: absolute;
+  top: 50%;
+  left: calc(100% + 10px);
+  transform: translateY(-50%);
+  font-size: 12px;
+}
+
+/* 一级页面卡片上下结构结束 */
+
+
+.form-container {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  padding-right: 6px;
+  position: relative;
+}
+
+.form-container .content-box {
+  height: calc(100% - 80px);
+  overflow-y: auto;
+  padding: 25px 24px;
+  box-sizing: border-box;
+}
+
+.form-container .content-box .table-container {
+  width: 100%;
+  border-collapse: collapse;
+  font-size: 16px;
+  color: #333;
+  table-layout: fixed;
+}
+
+
+.form-container th {
+  /* width: 200px; */
+  height: 60px;
+  text-align: right;
+  font-weight: normal;
+  background: #f8f9fb;
+  padding: 15px;
+  color: #666666;
+  border: 1px solid #e2e4ec;
+  font-size: 16px;
+}
+
+.form-container td {
+  width: 360px;
+  height: 60px;
+  padding: 0;
+  box-sizing: border-box;
+  border: 1px solid #e2e4ec;
+  position: relative;
+}
+
+.form-container .required {
+  position: absolute;
+
+  height: 100%;
+  width: 0;
+  top: 0;
+  left: 0;
+  border-left: 2px solid #ff0000;
+}
+
+.form-container .photo {
+  width: 100%;
+  /* height: 240px; */
+  display: flex;
+  flex-direction: row;
+  /* justify-content: space-between; */
+  align-items: flex-end;
+  padding: 15px;
+  gap: 15px;
+}
+
+
+
+/* .form-container .photo>.left {
+  height: 214px;
+  border-radius: 2px;
+  position: relative;
+  padding: 0 5px;
+} */
+
+.form-container .left>div.content {
+  width: 100%;
+  height: 100%;
+  background: #ebebeb;
+}
+
+.form-container .left>div.content>div.icon {
+  position: absolute;
+  top: 30px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.form-container .left>div.content>div.text {
+  position: absolute;
+  left: 50%;
+  bottom: 35px;
+  transform: translateX(-50%);
+  font-size: 16px;
+}
+
+.form-container .right {
+  display: flex;
+  align-items: flex-end;
+  justify-content: center;
+}
+
+.form-container .right>div.content {
+  width: 144px;
+  height: 144px;
+  background: #ebebeb;
+  opacity: 1;
+  border: 1px solid #edeff0;
+  border-radius: 50%;
+  position: relative;
+}
+
+.form-container .right>div.content>div.icon {
+  position: absolute;
+  top: 20px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.form-container .right>div.content>div.text {
+  position: absolute;
+  bottom: 25px;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.form-container td>.input {
+  width: 100%;
+  height: 100%;
+}
+
+.form-container td>.area {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+}
+
+.form-container td>.area>div {
+  height: 100%;
+}
+
+.form-container  td>div.img {
+  height: 120px;
+  display: block;
+  padding: 8px 22px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.form-container  td>div.img>img {
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.form-container  td>div.p {
+  font-size: 16px;
+  color: #333333;
+  padding: 20px 22px;
+}
+
+
+
+.input-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.input-container>div {
+  position: absolute;
+}
+
+.input-container .input {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  position: relative;
+  --input-required-display: block;
+}
+
+.input-container>.input>input {
+  outline: unset;
+  border: unset;
+  background: unset;
+  width: 100%;
+  height: 100%;
+  font-size: inherit;
+  padding: 0 15px;
+  box-sizing: border-box;
+  text-overflow: ellipsis;
+}
+.input-container>.input>input::placeholder,.select-container .input>input::placeholder,.custom-date-picker .el-input__inner::placeholder,.custom-date-picker .el-input__inner::placeholder{
+  color: #999;
+}
+
+/* 选择框样式开始 */
+.select-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.select-container>div {
+  position: absolute;
+  z-index: 4;
+}
+
+.select-container .input {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  cursor: pointer;
+}
+
+.select-container .input>input {
+  outline: unset;
+  border: unset;
+  background: unset;
+  width: 100%;
+  height: 100%;
+  padding: 0 15px;
+  font-size: inherit;
+  color: #000;
+  /* pointer-events: none; */
+}
+.select-container .input>input::placeholder{
+  color: #999;
+}
+.select-container .suffix {
+  position: absolute;
+  top: 0;
+  right: 0;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 15px 0;
+  z-index: 11;
+}
+
+.select-container .suffix>div{
+  width: 37px;
+  height: 37px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  opacity: 1;
+  background: var(--icon-bg, transparent);
+  color: #c3c7cb;
+  border-radius: 4px;
+}
+
+.select-container .suffix>div.select {
+  --icon-bg: #393d51;
+  color: #ffffff !important;
+}
+
+
+.select-container .popup-win {
+  width: 100%;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 999;
+  padding-top: 10px;
+  --popup-content-bg: #393d51;
+}
+
+.select-container .popup-win.bottom {
+  top: calc(100% - var(--select-popup-bottom-offset, 10px));
+}
+
+.select-container .popup-win.bottom::after {
+  content: "";
+  width: 14px;
+  height: 14px;
+  background: var(--popup-content-bg);
+  position: absolute;
+  right: 28px;
+  transform: rotate(45deg);
+  top: 5px;
+}
+.select-container .popup-win.top {
+  bottom: calc(100%);
+}
+
+.select-container .popup-win.top::after {
+  content: "";
+  width: 14px;
+  height: 14px;
+  background: var(--popup-content-bg);
+  position: absolute;
+  right: 28px;
+  transform: rotate(45deg);
+  bottom: -5px;
+}
+
+.select-container .popup-content {
+  background: var(--popup-content-bg);
+  position: relative;
+  border-radius: 4px;
+  color: #fff;
+  padding: 15px 2px;
+}
+
+.select-container .popup-win .content-area {
+  width: 99.5%;
+  max-height: 200px;
+  overflow-y: auto;
+  --scrollbar-track-color: transparent;
+  --scrollbar-thumb-color: #000;
+}
+
+
+.select-container .popup-win .content-area::-webkit-scrollbar {
+  width: 10px;
+  height: 10px;
+}
+
+.select-container .popup-win .content-area::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  background: var(--scrollbar-thumb-color, transparent);
+}
+
+.select-container .popup-win .content-area::-webkit-scrollbar-track {
+  border-radius: 10px;
+  background: var(--scrollbar-track-color, transparent);
+}
+
+.select-container .popup-win .content-area>div {
+  width: 98.5%;
+  position: relative;
+  height: 36px;
+  padding: 0 22px;
+  font-size: 14px;
+  color: var(--item-color, #fff);
+  background: var(--item-bg, transparent);
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  cursor: pointer;
+}
+
+.select-container .popup-win .content-area>div:hover {
+  --item-color: #000;
+  --item-bg: #fffdfd;
+}
+
+.select-container .popup-win .content-area>div>span.check-icon {
+  position: absolute;
+  top: 50%;
+  transform: translateY(-50%) scale(0.75);
+  left: 0;
+  padding-right: 8px;
+  visibility: var(--check-icon-visible, hidden);
+}
+
+.select-container .popup-win .content-area>div.active {
+  --check-icon-visible: visible;
+}
+
+/* radio */
+.radio-container {
+  display: flex;
+  align-content: flex-start;
+  gap: 20px;
+  padding: 0 20px;
+}
+
+.radio-container>div {
+  position: relative;
+  padding: 5px 10px;
+  border: 1px solid #bfc1c6;
+  border-radius: 2px;
+  overflow: hidden;
+  cursor: pointer;
+  text-align: center;
+  --radio-color: #c3c6ca;
+  color: var(--radio-color);
+}
+
+.radio-container .checked {
+  --radio-color: #393d51;
+}
+
+.radio-container .mark {
+  position: absolute;
+  bottom: 1px;
+  right: 0;
+  color: inherit;
+  width: 18px;
+  height: 18px;
+}
+
+.radio-container2 {
+  display: inline-flex;
+  align-content: flex-start;
+  gap: 20px;
+  margin-left: 15px;
+}
+
+.radio-container2>div {
+  position: relative;
+  padding: 5px 18px;
+  border: 1px solid #bfc1c6;
+  border-radius: 2px;
+  overflow: hidden;
+  cursor: pointer;
+  text-align: center;
+  --radio-color: #c3c6ca;
+  color: var(--radio-color);
+}
+
+.radio-container2 .checked {
+  --radio-color: #393d51;
+}
+
+.radio-container2 .mark {
+  position: absolute;
+  bottom: 1px;
+  right: 0;
+  color: inherit;
+  width: 18px;
+  height: 18px;
+}
+/* textarea */
+
+.textarea-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.textarea-container>div {
+  position: absolute;
+}
+
+.textarea-container .textarea {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+}
+
+.textarea-container textarea {
+  outline: unset;
+  border: unset;
+  background: unset;
+  width: 100%;
+  height: 100%;
+  padding: 15px;
+  line-height: 2em;
+  font-size: inherit;
+  resize: unset;
+}
+.textarea-container textarea::placeholder{
+  color: #999;
+}
+/* 错误提示开始 */
+.err-tip {
+  --err-tip-color: #ef5d0c;
+  font-size: 12px;
+  color: var(--err-tip-color);
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  cursor: pointer;
+  position: relative;
+  line-height: 15px;
+}
+
+.err-tip>div.tip {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  width: 100%;
+  padding: 5px 15px 2px 15px;
+}
+
+.err-tip::after {
+  content: "";
+  position: absolute;
+  bottom: 0;
+  left: 2px;
+  width: calc(100% - 2px* 2);
+  /* border-bottom: 2px solid var(--err-tip-color); */
+  z-index: 1;
+}
+
+.err-tip:hover {
+  --more-tip-visible: visible;
+  --more-tip-opacity: 1;
+}
+
+.err-tip>.tip-more {
+  transition: opacity 0.2s ease-in-out 0.6s;
+  opacity: var(--more-tip-opacity, 0);
+  visibility: var(--more-tip-visible, hidden);
+  background: #ffffff;
+  border-radius: 4px;
+  border: 1px solid var(--err-tip-color);
+  position: absolute;
+  top: 0;
+  left: 2px;
+  width: calc(100% - 2px* 2);
+  padding: 4px 12.5px;
+  z-index: 5;
+}
+.err-tip>.tip-more>p{
+  margin: 0;
+  background-color: #ffffff;
+}
+
+/* 错误提示开始 */
+.validate-vline{
+  width:6px;
+  height:100%;
+  position:absolute;
+  left:0;
+  top:0;
+  background-color:#ff0000;
+}
+.validate-tip {
+  --err-tip-color: #ef5d0c;
+  font-size: 16px;
+  color: var(--err-tip-color);
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  cursor: pointer;
+  position: relative;
+  line-height: 15px;
+}
+
+.validate-tip>div.tip {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  width: 100%;
+  padding: 5px 15px 2px 10px;
+}
+
+.validate-tip::after {
+  content: "";
+  position: absolute;
+  bottom: 0;
+  left: 2px;
+  width: calc(100% - 2px* 2);
+  /* border-bottom: 2px solid var(--err-tip-color); */
+  z-index: 1;
+}
+
+.validate-tip:hover {
+  --more-tip-visible: visible;
+  --more-tip-opacity: 1;
+}
+
+.validate-tip>.tip-more {
+  transition: opacity 0.2s ease-in-out 0.6s;
+  opacity: var(--more-tip-opacity, 0);
+  visibility: var(--more-tip-visible, hidden);
+  background: #fff;
+  border-radius: 4px;
+  border: 1px solid var(--err-tip-color);
+  position: absolute;
+  top: 0;
+  left: 2px;
+  width: calc(100% - 2px* 2);
+  padding: 4px 12.5px;
+  z-index: 3;
+}
+/* 错误提示结束 */
+.floating-div {
+  background-color: white;
+  position: absolute;
+  padding: 5px;
+  width: 100%;
+  /* 或根据需要调整 */
+  top: 16px;
+  z-index: 11;
+  left: 7px;
+  border: 1px solid #ccc;
+  height: auto;
+  box-sizing: border-box;
+  /* 其他样式 */
+}
+
+.floating-div textarea {
+  /* 设置 textarea 的样式 */
+  width: 100%;
+  height: 100px;
+  resize: none;
+  border: none;
+  outline: none;
+  height: auto;
+  overflow: hidden;
+  line-height: 20px;
+  font-size: 16px;
+  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+/* 弹窗头部样式开始 */
+.header-container {
+  width: 100%;
+  height: 100%;
+  padding-left: var(--space-size);
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.header-container .title {
+  font-size: 18px;
+}
+
+.header-container .title.visibility {
+  --title-visibility: visible;
+}
+
+.header-container .title:hover {
+  --header-icon-refresh: block;
+  --header-icon-normal: none;
+}
+
+.header-container .normal {
+  display: var(--header-icon-normal);
+}
+
+.header-container .hover {
+  display: var(--header-icon-refresh);
+  cursor: pointer;
+}
+
+.header-container .handle-bar {
+  --pop-win-header-color: #c3c6ca;
+  color: var(--pop-win-header-color);
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.header-container .left-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 6px;
+  padding-right: 14px;
+  color: inherit;
+  margin-right: 54px;
+}
+
+.header-container .left-bar .dialog-icon {
+  cursor: pointer;
+  padding: 6px;
+  width: 36px;
+  height: 36px;
+  border-radius: 4px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.header-container .left-bar .dialog-icon:hover {
+  background: #c4c7cc;
+  color: #fff;
+}
+
+.header-container .setting {
+  visibility: var(--block-title-visible, hidden);
+  width: 60px;
+  height: 60px;
+  border-top-right-radius: 4px;
+  position: relative;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.header-container .setting:hover {
+  color: #fff;
+  background: #575d6d;
+}
+
+.header-container .setting:hover::before {
+  display: none;
+}
+
+.header-container .close-bar {
+  width: 60px;
+  height: 60px;
+  border-top-right-radius: 4px;
+  position: relative;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.header-container .close-bar::before {
+  width: 0;
+  height: 24px;
+  border-left: 1px solid #c3c6ca;
+  content: "";
+  position: absolute;
+  top: 50%;
+  left: 0;
+  transform: translateY(-50%);
+}
+
+.header-container .close-bar:hover {
+  color: #fff;
+  background: #575d6d;
+}
+
+.header-container .close-bar:hover::before {
+  display: none;
+}
+/* 弹窗头部样式结束 */
+
+
+/* 弹窗样式开始 */
+.popup-container {
+  height: 100%;
+  width: 100%;
+  background: var(--white);
+  font-size: initial;
+  box-shadow: 10px 0px 10px 0px rgba(0, 0, 0, 0.3);
+  border-radius: 4px;
+}
+
+
+.popup-container>div {
+  width: 100%;
+}
+
+.popup-container .header {
+  height: 60px;
+  border-bottom: 2px solid var(--lightgray);
+  background-color: white;
+  border-radius: 4px;
+}
+
+.popup-container .body {
+  height: calc(100% - 60px);
+}
+
+.popup-container .dialog-body {
+  width: 500px;
+  height: 300px;
+  background: red;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  position: absolute;
+}
+
+.dialog-container {
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  top: 0;
+  left: 0;
+  pointer-events: none;
+  background: transparent;
+  font-size: 0;
+  z-index: 1000;
+}
+
+.dialog-container .mark-content {
+  width: 100%;
+  height: 100%;
+  pointer-events: all;
+  position: relative;
+  -webkit-backdrop-filter: blur(3px);
+  backdrop-filter: blur(3px);
+  background: rgba(0, 0, 0, 0.2);
+}
+
+/* 登录部分 */
+
+.login-container {
+  width: 100%;
+  height: 100%;
+  background-size: cover;
+  background-color: antiquewhite;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  position: fixed;
+  z-index: 99999;
+  left: 0;
+  top: 0;
+}
+
+.login-container>div {
+  height: 100%;
+}
+
+.login-container .left {
+  width: calc(100% - 510px);
+}
+
+.login-container .right {
+  width: 510px;
+  background: rgba(255, 255, 255, 0.2);
+  position: relative;
+}
+
+.login-container .right>div.content-area {
+  height: calc(100% - 70px);
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.login-container .login-box {
+  width: 432px;
+  height: 494px;
+  background: rgba(255, 255, 255, 0.9);
+  box-shadow: 0px 5px 5px 0px rgba(0, 0, 0, 0.2);
+  border-radius: 4px;
+}
+
+.login-container .login-box>div {
+  width: 100%;
+}
+
+.login-container .box-header {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 42px;
+}
+
+.login-container .box-header>img {
+  width: 348px;
+  height: 98px;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.login-container .box-container {
+  height: calc(100% - 182px - 40px);
+  position: relative;
+}
+
+.login-container .box-form {
+  padding: 0 37px;
+}
+
+.login-container>div.right>div.content-area>div.login-box>div.box-container>form.box-form>div.form-item {
+  width: 100%;
+  height: 37px;
+  position: relative;
+  display: flex;
+  margin-bottom: 20px;
+  background: #ffffff;
+  border: 1px solid #575d6d;
+  border-radius: 4px;
+}
+
+.login-container .icon {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  width: 46px;
+  height: 100%;
+  background: #575d6d;
+  color: #fff;
+}
+
+.login-container .icon-container {
+  display: block;
+}
+
+.login-container .check-code {
+  width: 140px;
+  height: 35px;
+}
+
+.login-container .check-code img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+}
+
+.login-container .input,
+.login-container .select {
+  flex: 1;
+  height: 100%;
+}
+
+.login-container .input input,
+.login-container .select input,
+.login-container .input select,
+.login-container .select select {
+  width: 100%;
+  height: 100%;
+  outline: none;
+  border: unset;
+  background: transparent;
+  padding: 0 10px;
+  font-size: 18px;
+  color: #333;
+}
+
+.login-container .form-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.login-button {
+  cursor: pointer;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 10px;
+  width: 161px;
+  height: 37px;
+  background: #ffffff;
+  border-radius: 4px;
+  outline: unset;
+  font-size: 18px;
+  --btn-color: #333333;
+  --btn-bg: #fff;
+  --btn-border-color: #575d6d;
+  color: var(--btn-color);
+  background-color: var(--btn-bg);
+  border: 1px solid var(--btn-border-color);
+}
+
+.login-button[theme="primary"],
+.login-button:hover {
+  --btn-bg: #575d6d;
+  --btn-color: #fff;
+}
+
+.login-container .err-tip {
+  bottom: -32px;
+  position: absolute;
+  padding-left: 40px;
+}
+
+.login-container .err-tip::after {
+  bottom: -8px;
+}
+
+.login-container .time {
+  position: absolute;
+  left: 10px;
+  width: 12px;
+  bottom: 0;
+}
+
+.login-container .time>div {
+  width: 12px;
+  height: 12px;
+  opacity: 1;
+  margin-bottom: 8px;
+  border-radius: 50%;
+  border: 1px solid #ef5d0c;
+}
+
+.login-container .fill {
+  background: #ef5d0c;
+}
+
+.login-container .box-container>div.err-tip>div.tip {
+  color: #ef5d0c;
+  font-size: 18px;
+  bottom: -30px;
+  left: 10px;
+  padding: 5px 15px 2px 0;
+}
+
+.login-container .box-footer {
+  height: 40px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.login-container .box-footer>div {
+  height: 100%;
+}
+
+.login-container .box-footer>div.left {
+  width: calc(100% - 40px);
+}
+
+.login-container .box-footer>div.right {
+  width: 40px;
+  cursor: pointer;
+}
+
+.login-container .footer {
+  padding: 0 40px;
+  height: 70px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  font-size: 18px;
+  color: #fff;
+}
+
+.login-container .mask {
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  z-index: 100;
+  position: absolute;
+  background: rgba(255, 255, 255, 0.2);
+  padding-bottom: 70px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.login-container .qrcode-box {
+  width: 432px;
+  height: 494px;
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 4px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+}
+
+.login-container .qrcode-box::after {
+  content: "";
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 0;
+  background: rgba(0, 0, 0, 0.2);
+  filter: blur(1px);
+}
+
+.login-container .qr {
+  width: 340px;
+  height: 340px;
+  position: absolute;
+  z-index: 1;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  background: #f7f7f7;
+  box-shadow: 5px 0px 5px 0px rgba(0, 0, 0, 0.2);
+  border-radius: 4px;
+  padding: 20px;
+}
+
+.login-container .qr>img {
+  user-drag: none;
+  -webkit-user-drag: none;
+  -khtml-user-drag: none;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+  width: 100%;
+  height: 100%;
+}
+
+.login-container>div.right>div.mask>div.qrcode-box>div.tip {
+  position: absolute;
+  bottom: 1em;
+  left: 0;
+  width: 100%;
+  text-align: center;
+  z-index: 10;
+  font-size: 18px;
+  color: #ff0000;
+}
+
+.lockscreen-container .login-box{
+  height: auto;
+  position: relative;
+}
+.lockscreen-container .box-header{
+  display: flex;
+  flex-direction: column;
+  padding: 15px;
+  margin: 41px 0;
+}
+.lockscreen-container .box-header img{
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+}
+.lockscreen-container .right{
+  opacity: 0;
+  visibility: hidden;
+  transition: opacity 0.3s ease, visibility 0.3s ease;
+}
+  
+.lockscreen-container .right--visible {
+  opacity: 1;
+  visibility: visible;
+}
+.lockscreen-container  .left {
+  cursor: pointer;
+}
+/* 登陆相关结束  */
+
+/* 首页组件头部 */
+.edit-box-header-container {
+  width: 100%;
+  height: 100%;
+  padding-left: var(--space-size);
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.edit-box-header-container .title {
+  font-size: 18px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+  visibility: var(--title-visibility, hidden);
+  --header-icon-refresh: none;
+  --header-icon-normal: block;
+}
+
+.edit-box-header-container .title.visibility {
+  --title-visibility: visible;
+}
+
+.edit-box-header-container .title:hover {
+  --header-icon-refresh: block;
+  --header-icon-normal: none;
+}
+
+.edit-box-header-container .normal {
+  display: var(--header-icon-normal);
+}
+
+.edit-box-header-container .hover {
+  display: var(--header-icon-refresh);
+  cursor: pointer;
+}
+
+.edit-box-header-container .handle-bar {
+  --pop-win-header-color: #c3c6ca;
+  color: var(--pop-win-header-color);
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.edit-box-header-container .left-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 12px;
+  padding-right: 14px;
+  color: inherit;
+}
+
+.edit-box-header-container .left-bar .icon-container {
+  cursor: pointer;
+  padding: 6px;
+  width: 36px;
+  height: 36px;
+  border-radius: 4px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.edit-box-header-container .left-bar .icon-container:hover {
+  background: #c4c7cc;
+  color: #fff;
+}
+
+.edit-box-header-container .setting {
+  visibility: var(--block-title-visible, hidden);
+  width: 60px;
+  height: 60px;
+  border-top-right-radius: 4px;
+  position: relative;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.edit-box-header-container .setting:hover {
+  color: #fff;
+  background: #575d6d;
+}
+
+.edit-box-header-container .setting:hover::before {
+  display: none;
+}
+
+.user-info-container {
+  width: 590px;
+  height: 400px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: var(--white);
+  border-radius: 2px;
+  --block-title-visible: hidden;
+}
+
+.user-info-container:hover {
+  --block-title-visible: visible;
+  box-shadow: 0 0 0 8px #dddfe6;
+  border-radius: 1px;
+}
+
+
+.user-info-container .body {
+  padding: 0 var(--space-size, 20px) var(--space-size, 20px) var(--space-size, 20px);
+}
+
+.user-info-container  .user-info {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.user-info-container .avatar {
+  width: 94px;
+  height: 94px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.user-info-container  .info {
+  width: calc(100% - 120px);
+}
+
+.user-info-container  .info>p {
+  padding: 0;
+  margin: 0;
+  cursor: pointer;
+}
+
+.user-info-container  .info>p:first-child {
+  font-size: 16px;
+  color: #333;
+  margin-bottom: 10px;
+}
+
+.user-info-container  .info>p:not(:first-child) {
+  font-size: 14px;
+  color: #808080;
+  line-height: 22px;
+}
+
+.user-info-container  .progress-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.user-info-container .progress {
+  width: calc(100% - 0px);
+  height: 20px;
+  font-size: 12px;
+  padding: 0 90px 0 10px;
+  background: var(--lightgray);
+  border-radius: 10px;
+  --progress-color: #666666;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.user-info-container .progress:hover {
+  --progress-color: #0072f1;
+}
+
+.user-info-container .line {
+  background: var(--progress-color);
+  width: 0%;
+  height: 4px;
+  position: relative;
+  border-radius: 2px;
+}
+
+.user-info-container .line>div {
+  position: absolute;
+  top: 50%;
+  left: calc(100% + 1em);
+  transform: translateY(-50%);
+  width: 5.5em;
+}
+
+.user-info-container .bar {
+  padding-left: 10px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  height: 0px;
+  cursor: pointer;
+}
+
+.user-info-container .other-info {
+  padding: 10px 0;
+  color: #666;
+  font-size: 16px;
+}
+
+.user-info-container  .other-info>div {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 20px;
+  padding: 15px 0;
+}
+
+.edit-box-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  overflow: hidden;
+}
+
+.edit-box-container>div {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+
+.edit-box-container .edit-tools {
+  --direction-icon-visible: hidden;
+  display: var(--edit-box-tools-display, none);
+  z-index: 2;
+}
+
+.edit-box-container .edit-tools:hover,
+.edit-box-container .edit-tools.active {
+  --direction-icon-visible: visible;
+}
+
+.edit-box-container .edit-tools>div {
+  position: absolute;
+  pointer-events: all;
+  cursor: pointer;
+  display: flex;
+}
+
+.edit-box-container .close {
+  height: 36px;
+  width: 36px;
+  top: 0;
+  right: 0;
+  color: var(--edit-tool-bar-close-color, #c3c6ca);
+  visibility: var(--direction-icon-visible);
+}
+
+.edit-box-container .close:hover {
+  --edit-tool-bar-close-color: #575d6d;
+}
+
+.edit-box-container .right-center {
+  visibility: var(--direction-icon-visible);
+  height: 30px;
+  width: 30px;
+  top: 50%;
+  transform: translateY(-50%);
+  right: 0;
+  justify-content: flex-end;
+  align-items: flex-end;
+}
+
+.edit-box-container .right-center::before {
+  content: "";
+  right: 0;
+  top: 0;
+  width: 4px;
+  height: 100%;
+  background: #999999;
+  border-radius: 2px;
+  position: absolute;
+}
+
+.edit-box-container .right-center .icon {
+  height: 30px;
+  width: 30px;
+  transform: rotate(90deg);
+}
+
+.edit-box-container .right-bottom {
+  visibility: var(--direction-icon-visible);
+  width: 36px;
+  height: 36px;
+  bottom: 0;
+  right: 0;
+  justify-content: flex-end;
+  align-items: flex-end;
+}
+
+.edit-box-container .right-bottom::before {
+  content: "";
+  right: 0;
+  top: 0;
+  width: 3px;
+  height: 100%;
+  background: #999999;
+  border-radius: 2px;
+  position: absolute;
+}
+
+.edit-box-container .right-bottom::after {
+  content: "";
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  height: 3px;
+  background: #999999;
+  border-radius: 2px;
+  position: absolute;
+}
+
+.edit-box-container .right-bottom>.icon {
+  width: 30px;
+  height: 30px;
+  transform: rotate(-45deg);
+}
+
+.edit-box-container .bottom-center {
+  visibility: var(--direction-icon-visible);
+  height: 36px;
+  width: 36px;
+  left: 50%;
+  transform: translateX(-50%);
+  bottom: 0;
+  justify-content: center;
+  align-items: flex-end;
+}
+
+.edit-box-container .bottom-center::before {
+  content: "";
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  height: 4px;
+  background: #999999;
+  border-radius: 2px;
+  position: absolute;
+  z-index: 0;
+}
+
+.edit-box-container .bottom-center>.icon {
+  height: 30px;
+  width: 30px;
+  transform: rotate(180deg);
+}
+
+.edit-box-container>.content-area {
+  z-index: 1;
+}
+
+.page-content {
+  width: 100%;
+  height: 100%;
+  padding: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  gap: 15px;
+  overflow-y: hidden;
+  background: var(--lightgray);
+}
+
+.page-content:hover {
+  overflow-y: auto;
+}
+
+.folder-container {
+  width: 100%;
+  height: 100%;
+  overflow-y: hidden;
+}
+
+.folder-container:hover {
+  overflow-y: auto;
+}
+
+.folder-container .group-item {
+  --hover-bg: #edf1f5;
+  padding-right: 6px;
+  color: #333;
+}
+
+.folder-container  .group-title {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+  color: #333;
+  cursor: pointer;
+  padding: 15px var(--space-size, 20px);
+}
+
+.folder-container .group-title:hover {
+  background: var(--hover-bg);
+}
+
+.folder-container .group-title>div.folder {
+  position: relative;
+}
+
+.folder-container .group-title>div.folder::after {
+  content: attr(data-num);
+  position: absolute;
+  font-size: 14px;
+  color: #999;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -45%) scale(0.9);
+}
+
+.folder-container .group-childs {
+  padding-left: 40px;
+  margin: 0;
+}
+
+.folder-container .group-childs>li {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  list-style-type: none;
+  cursor: pointer;
+  position: relative;
+  padding: 12px 5px 12px 20px;
+  border-bottom: 1px solid #eee;
+}
+
+.folder-container .group-childs>li::before {
+  position: absolute;
+  content: "";
+  top: 50%;
+  left: 5px;
+  transform: translateY(-50%);
+  width: 0.25em;
+  height: 0.25em;
+  border-radius: 50%;
+  background-color: #666;
+}
+
+.folder-container .group-childs>li:hover {
+  background: var(--hover-bg);
+}
+
+.folder-container .group-childs>li>div:first-child {
+  color: #333;
+  font-size: 16px;
+}
+
+.folder-container .group-childs>li>div:nth-child(2) {
+  color: #999;
+}
+
+.todo-list-container {
+  width: 590px;
+  height: 400px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: var(--white);
+  border-radius: 2px;
+  --block-title-visible: hidden;
+}
+
+.todo-list-container:hover {
+  --block-title-visible: visible;
+  box-shadow: 0 0 0 8px #dddfe6;
+  border-radius: 1px;
+}
+
+.todo-list-container .body {
+  border-top: 1px solid #eaeaea;
+  height: calc(100% - 57px);
+  overflow-y: hidden;
+  padding: 12px 6px 12px 0px;
+  box-sizing: border-box;
+}
+
+.notice-list-container {
+  width: 590px;
+  height: 242px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: var(--white);
+  border-radius: 2px;
+  --block-title-visible: hidden;
+}
+
+.notice-list-container:hover {
+  --block-title-visible: visible;
+  box-shadow: 0 0 0 8px #dddfe6;
+  border-radius: 1px;
+}
+
+.notice-list-container .header {
+  border-bottom: 1px solid #eaeaea;
+}
+
+.notice-list-container .body {
+  width: calc(100% - 6px);
+
+  height: calc(100% - 57px);
+  overflow-y: hidden;
+  padding: 12px var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+}
+
+.notice-list-container .body:hover {
+  overflow-y: auto;
+}
+
+.notice-list-container .body>div {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px 0;
+}
+
+.notice-list-container .body>div>div:first-child {
+  gap: 5px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.notice-list-container .body>div>div:nth-child(2) {
+  color: #999999;
+}
+
+.launch-container {
+  width: 590px;
+  height: 204px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: var(--white);
+  border-radius: 2px;
+  --block-title-visible: hidden;
+}
+
+.launch-container:hover {
+  --block-title-visible: visible;
+  box-shadow: 0 0 0 8px #dddfe6;
+  border-radius: 1px;
+}
+
+.launch-container .body {
+  border-top: 1px solid #eaeaea;
+  height: calc(100% - 57px);
+  overflow-y: auto;
+  padding: 12px var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #808080;
+  display: flex;
+  align-content: flex-start;
+  flex-wrap: wrap;
+  font-size: 12px;
+  gap: 20px;
+}
+
+.launch-container .body>div {
+  cursor: pointer;
+  width: 60px;
+  height: 100px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+}
+
+.launch-container .body>div:hover {
+  --popup-visible: visible;
+}
+
+.launch-container .body>div>.common-icon {
+  color: #b4b5b5;
+  width: 60px;
+  height: 60px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  background: var(--item-bg, transparent);
+  position: relative;
+  --item-mark-color: #999999;
+}
+
+.launch-container .body>div>.common-icon:hover {
+  --item-bg: #edf1f5;
+  --item-mark-color: #3a3e51;
+}
+
+.launch-container .body>div>.common-icon.mark-down::after {
+  content: "";
+  width: 0;
+  height: 0;
+  border-width: 6px 6px 6px 6px;
+  border-style: solid;
+  border-color: transparent var(--item-mark-color) var(--item-mark-color) transparent;
+  position: absolute;
+  bottom: 0;
+  right: 0;
+}
+
+.launch-container  .text {
+  padding-top: 4px;
+  font-size: 16px;
+}
+
+.launch-container .popup {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 130px;
+  height: 90px;
+  --popup-bg: #3a3e51;
+  visibility: var(--popup-visible, hidden);
+  background: var(--popup-bg);
+  padding: 16px 2px 0 2px;
+  border-radius: 4px;
+  z-index: 1111;
+}
+
+.launch-container .popup::before {
+  width: 100%;
+  height: 12px;
+  background: transparent;
+  content: "";
+  position: absolute;
+  top: -12px;
+  left: 0;
+}
+
+.launch-container .popup::after {
+  content: "";
+  background: var(--popup-bg);
+  width: 12px;
+  height: 12px;
+  position: absolute;
+  top: -6px;
+  right: 30px;
+  transform: rotate(45deg);
+}
+
+.launch-container .popup>div {
+  height: 36px;
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  padding: 0 15px;
+  font-size: 14px;
+  background: var(--item-bg, transparent);
+  color: var(--item-color, #fff);
+}
+
+.launch-container .popup>div:hover {
+  --item-bg: #fff;
+  --item-color: #333;
+}
+
+.statistics-container {
+  width: 1200px;
+  height: 475px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: var(--white);
+  border-radius: 2px;
+  --block-title-visible: hidden;
+}
+
+.statistics-container:hover {
+  --block-title-visible: visible;
+  box-shadow: 0 0 0 8px #dddfe6;
+  border-radius: 1px;
+}
+
+.statistics-container .body {
+  /* border-top: 1px solid #eaeaea; */
+  height: calc(100% - 57px);
+  overflow-y: auto;
+  padding: 12px var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+}
+
+.statistics-container .body .chart-container {
+  width: 100%;
+  height: 100%;
+}
+
+.page-container {
+  width: 100%;
+  height: 100%;
+  /* padding: 20px 0; */
+}
+
+.page-container[sys-mode="edit"] {
+  --edit-box-tools-display: block;
+}
+
+.page-container .search-bar {
+  margin-top: 20px;
+  width: 100%;
+  height: 40px;
+  position: relative;
+}
+
+.page-container .item-content-area {
+  height: calc(100% - 75px);
+  width: 100%;
+  margin-top: 10px;
+  padding: 10px 0 100px 20px;
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  overflow-y: auto;
+  --project-detail-width: 370px;
+}
+
+.page-container .content-area .pager-bar {
+  width: 100%;
+  height: 80px;
+  padding: 20px;
+}
+
+.page-container .content-area>div.project-detail {
+  padding-right: 20px;
+  width: var(--project-detail-width);
+  height: 100%;
+}
+
+/* 分页开始 */
+.pager-container {
+  width: 98%;
+  margin: 0 auto;
+  /* height: 100%; */
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.pager-container .pager-content {
+  border-radius: 4px;
+  height: 32px;
+  color: #999999;
+  font-size: 18px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.pager-container .pager-content>div {
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.pager-container  .info {
+  padding: 0 20px;
+  border: 1px solid var(--btn-border, #c4c7cc);
+  border-top-left-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+
+.pager-container .btn>button {
+  height: 100%;
+  background: #edf1f5;
+  width: 84px;
+  outline: unset;
+  cursor: pointer;
+  font-size: inherit;
+  color: var(--btn-color, #999999);
+  border: 1px solid var(--btn-border, #c4c7cc);
+}
+
+.pager-container .btn>button:hover {
+  --btn-border: transparent;
+  --btn-color: #fff;
+  background: #393d51;
+}
+
+.pager-container .btn:last-child>button {
+  border-top-right-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+
+/* 分页结束 */
+/* 一级页面右边信息栏开始 */
+.info-container {
+  width: 100%;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 2px;
+  position: relative;
+  overflow-y: auto;
+  height: 100%;
+}
+
+.info-container .header {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 10px 20px;
+  border-bottom: 1px solid #cfd2d7;
+}
+
+.info-container .header>div {
+  height: 40px;
+  display: flex;
+  align-items: center;
+}
+
+.info-container .header>div:first-child {
+  width: 80px;
+}
+
+.info-container .header>div:last-child {
+  padding-left: 5px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: flex-end;
+  width: calc(70%);
+  color: #333333;
+  font-size: 18px;
+}
+
+.info-container .header>div:last-child>div {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.info-container .section-container {
+  padding: 0 20px;
+}
+
+.info-container  .section {
+  padding: 8px 0;
+  --title-tip-height: 6px;
+}
+
+.info-container   .section:not(:last-child) {
+  border-bottom: 1px solid #edf1f5;
+}
+
+.info-container   .section:hover {
+  --title-tip-height: 18px;
+}
+
+.info-container   .section>div.title {
+  color: #333333;
+  font-size: 18px;
+  line-height: 3em;
+  position: relative;
+  padding-left: 20px;
+}
+
+.info-container   .section .title:before {
+  transition: height 0.5s;
+  content: "";
+  width: 6px;
+  height: var(--title-tip-height);
+  border-radius: 3px;
+  position: absolute;
+  left: 5px;
+  top: 50%;
+  transform: translateY(-50%);
+  background: #333;
+}
+
+.info-container   .section> .a {
+  --a-color: #333;
+  color: var(--a-color);
+  font-size: 16px;
+  line-height: 2.5em;
+  cursor: pointer;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.info-container   .section .a:hover {
+  --a-color: #006cf1;
+}
+
+.info-container   .section .text {
+  color: #333333;
+  font-size: 16px;
+  line-height: 2.5em;
+}
+
+/* 一级页面右边信息栏结束 */
+
+/* 统计图 */
+.page-statistics .content-area {
+  padding: 20px;
+  height: calc(100% - 80px);
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  gap: 20px;
+  overflow-y: auto;
+}
+
+.project-report-statistics .statistics-container:hover {
+  --block-title-visible: visible;
+}
+
+.project-report-statistics  .body {
+  /* border-top: 1px solid #eaeaea; */
+  height: calc(100% - 57px);
+  overflow-y: auto;
+  padding: 12px var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+}
+
+.project-report-statistics  .table-container {
+  border: 1px solid #dddfe6;
+  margin-bottom: 22px;
+  overflow-x: auto;
+  background: var(--table-bg, #fff);
+}
+
+.project-report-statistics  .table-container::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+}
+
+.project-report-statistics  .table-container::-webkit-scrollbar-thumb {
+  border-radius: 0;
+  -webkit-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.2);
+  background: var(--scrollbar-thumb-color, #c1c1c1);
+}
+
+.project-report-statistics  .table-container::-webkit-scrollbar-track {
+  border-radius: 0;
+  -webkit-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.2);
+  background: var(--scrollbar-track-color, transparent);
+}
+
+.project-report-statistics  .table-container:hover {
+  --table-bg: #edf1f5;
+}
+
+.project-report-statistics  .title {
+  position: relative;
+  padding: 15px 20px 15px 35px;
+  font-size: 16px;
+  border-bottom: 1px solid #dddfe6;
+}
+
+.project-report-statistics  .title::before {
+  content: "";
+  position: absolute;
+  top: 50%;
+  left: 20px;
+  transform: translateY(-50%);
+  width: 5px;
+  height: 5px;
+  background: #333333;
+  border-radius: 50%;
+}
+
+.project-report-statistics  .table-columns {
+  display: flex;
+  flex-wrap: nowrap;
+}
+
+.project-report-statistics  .table-columns>div {
+  flex-shrink: 0;
+  padding: 10px 20px;
+  border-right: 1px solid #dddfe6;
+}
+
+/* 跨对象弹窗开始 */
+.search-dialog-content {
+  width: 900px;
+  height: 100vh;
+  position: relative;
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  font-size: initial;
+  color: #333;
+  /* padding: 0 100px; */
+  background: #ffffff;
+  /* box-shadow: 0px 10px 5px 0px rgba(0, 0, 0, 0.3); */
+  border-radius: 4px;
+  /* height: 100%; */
+  padding: 0 100px 30px 100px;
+}
+
+.search-dialog-content>div {
+  width: 100%;
+}
+
+.search-dialog-content .header {
+  height: 130px;
+}
+
+.search-dialog-content .input-area {
+  width: 100%;
+  height: 53px;
+  color: #666;
+  font-size: 18px;
+  position: relative;
+  border: 1px solid #999999;
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.search-dialog-content .input-area>input {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  line-height: 53px;
+  padding: 0 20px;
+  font-size: inherit;
+  outline: unset;
+  border: unset;
+  z-index: 1;
+}
+
+.search-dialog-content .search-btn {
+  position: absolute;
+  top: 0;
+  right: 0;
+  font-size: inherit;
+  color: inherit;
+  height: 100%;
+  padding: 0 17px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  z-index: 2;
+  --search-btn-bg: transparent;
+  --search-btn-color: #666666;
+  --search-btn-left-border-visible: visible;
+  background: var(--search-btn-bg);
+  color: var(--search-btn-color);
+}
+
+.search-dialog-content .search-btn:hover {
+  --search-btn-color: #fff;
+  --search-btn-bg: #242835;
+  --search-btn-left-border-visible: hidden;
+}
+
+.search-dialog-content .search-btn::after {
+  visibility: var(--search-btn-left-border-visible);
+  position: absolute;
+  top: 50%;
+  left: 0;
+  transform: translateY(-50%);
+  width: 0;
+  height: 60%;
+  border-left: 1px solid #999999;
+  content: "";
+}
+
+.search-dialog-content .sort {
+  padding: 10px 0;
+  font-size: 14px;
+  color: #a9a9a9;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.search-dialog-content .list {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+}
+
+.search-dialog-content .list>div {
+  padding: 5px 10px;
+  cursor: pointer;
+}
+
+.search-dialog-content .active {
+  background-color: #e8f9fc;
+  color: #0066ff;
+  border-radius: 2px;
+}
+
+.search-dialog-content .time {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  gap: 10px;
+}
+
+.search-dialog-content .res {
+  color: #999999;
+  font-size: 12px;
+}
+
+.search-dialog-content .search-res {
+  height: calc(100% - 130px);
+  overflow-y: auto;
+  padding: 10px 10px 0 0;
+  margin-bottom: 5px;
+}
+
+.search-dialog-content .search-item {
+  margin-bottom: 20px;
+}
+
+.search-dialog-content .search-item.style-1>div.title {
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+}
+
+.search-dialog-content .search-item.style-1>div.detail {
+  padding: 5px 0;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.search-dialog-content .search-item.style-1>div.detail>div.thumb {
+  width: 77px;
+  height: 95px;
+}
+
+.search-dialog-content .search-item.style-1>div.detail>div.thumb>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.search-dialog-content .search-item.style-1>div.detail>div.info {
+  width: calc(100% - 77px);
+  padding-left: 10px;
+}
+
+.search-dialog-content .search-item.style-1>div.detail>div.info>div.title,
+.search-dialog-content .search-item.style-1>div.detail>div.info>div.subtitle {
+  color: #333;
+  font-size: 16px;
+  line-height: 1.5em;
+}
+
+.search-dialog-content .search-item.style-1>div.detail>div.info>div.desc {
+  margin-top: 5px;
+  color: #666666;
+  font-size: 14px;
+}
+
+.search-dialog-content .search-item.style-2>div.title {
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+}
+
+.search-dialog-content .search-item.style-2>div.desc {
+  color: #666666;
+  font-size: 14px;
+}
+
+.search-dialog-content .search-item.style-3>div.title {
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+}
+
+.search-dialog-content .search-item.style-3>div.group-list {
+  margin-top: 10px;
+}
+
+.search-dialog-content .search-item.style-3 .gitem {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  align-items: flex-start;
+}
+
+.search-dialog-content .search-item.style-3 .gitem:not(:last-child) {
+  margin-bottom: 20px;
+}
+
+.search-dialog-content .search-item.style-3  .thumb {
+  width: 180px;
+  height: 99px;
+}
+
+.search-dialog-content .search-item.style-3  .thumb>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.search-dialog-content .search-item.style-3  .info {
+  width: calc(100% - 180px);
+  padding-left: 10px;
+}
+
+.search-dialog-content .search-item.style-3  .info>div.title {
+  color: #666666;
+  font-size: 16px;
+}
+
+.search-dialog-content .search-item.style-3  .info>div.desc {
+  margin-top: 5px;
+  color: #666666;
+  font-size: 14px;
+}
+
+.search-dialog-content .search-item.style-3  .info>div.source {
+  margin-top: 5px;
+  color: #666666;
+  font-size: 12px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 5px;
+}
+
+.search-dialog-content .search-item.style-3  .info>div.source .icon-container {
+  color: rgba(0, 0, 0, 0.3);
+}
+
+/* 跨对象弹窗结束 */
+
+/* 项目基本信息开始 */
+.project-edit-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  overflow: hidden;
+}
+
+.project-edit-container>div {
+  height: 100%;
+}
+
+.project-edit-container .left-side {
+  width: 180px !important;
+  border-right: 1px solid #e2e4ec;
+  background-color: #edf1f5;
+}
+
+.project-edit-container .left-side>div {
+  width: 100%;
+}
+
+.project-edit-container .menu-header {
+  height: 120px;
+  border-bottom: 1px solid #d8dae3;
+}
+
+.project-edit-container .menu-content {
+  height: calc(100% - 60px);
+}
+
+.project-edit-container .menu-content .scroll-view {
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
+  font-size: 18px;
+}
+
+.project-edit-container .menu-item,
+.project-edit-container .group .menu-item {
+  padding: 20px 12px 20px 30px;
+  cursor: pointer;
+  position: relative;
+  color: #333333;
+  display: flex;
+  align-items: center;
+}
+
+.project-edit-container .menu-item .arrow{
+  position: absolute;
+  left: 180px;
+}
+
+.menu-item-point{
+  width: 6px;
+  height: 6px;
+  display: block;
+  border-radius: 50%;
+  background: #666;
+  
+}
+
+.project-edit-container .menu-item>.icon-container,
+.project-edit-container .group .menu-item>.icon-container {
+  margin-left: 10px;
+}
+
+.project-edit-container .menu-item::after,
+.project-edit-container .group .menu-item::after {
+  content: "";
+  width: calc(100% - 10px * 2);
+  height: 0;
+  display: block;
+  position: absolute;
+  bottom: -1px;
+  left: 10px;
+  border-bottom: 1px solid #d8dae3;
+}
+
+.project-edit-container .menu-item.active,
+.project-edit-container .group .menu-item.active {
+  background: #fff;
+}
+
+.project-edit-container .menu-item.active::after,
+.project-edit-container .group .menu-item.active::after {
+  border-bottom-color: transparent;
+}
+
+.project-edit-container .group {
+  width: 100%;
+}
+
+/* .project-edit-container  .group-detail {
+  padding-left: 10px;
+} */
+
+.project-edit-container  .group-detail .menu-item {
+  padding-left: 44px;
+}
+
+/* .project-edit-container .group-detail .menu-item::before {
+  content: "";
+  height: 6px;
+  width: 6px;
+  border-radius: 50%;
+  position: absolute;
+  top: 50%;
+  left: 30px;
+  background: #666;
+  transform: translateY(-50%);
+  position: relative;
+} */
+
+.sub-tab-menu-footer {
+  height: 60px;
+  flex-shrink: 0;
+  background: #afb8d0;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 10px;
+  font-size: 20px;
+  color: #fff;
+  cursor: pointer;
+  position: relative;
+}
+
+.sub-tab-menu-footer:hover {
+  background: #393d51;
+}
+
+.sub-tab-menu-popup {
+  position: absolute;
+  bottom: 76px;
+  left: 0;
+  right: 0;
+  display: none;
+
+}
+
+.sub-tab-menu-popup>div {
+  height: 76px;
+  flex-shrink: 0;
+  background: #afb8d0;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 10px;
+  font-size: 20px;
+  color: #fff;
+  cursor: pointer;
+  position: relative;
+}
+
+.sub-tab-menu-popup>div::after {
+  content: "";
+  width: 90%;
+  height: 1px;
+  display: block;
+  position: absolute;
+  bottom: 0;
+  left: 50%;
+  transform: translateX(-50%);
+  background: #ffffff;
+}
+
+.sub-tab-menu-popup>div:hover {
+  background: #393d51;
+}
+
+/* 鼠标悬浮时显示弹出菜单 */
+.sub-tab-menu-footer:hover .sub-tab-menu-popup {
+  display: block;
+}
+
+.project-edit-container>div.content-area {
+  width: calc(100% - 180px);
+  overflow-y: auto;
+}
+
+/* 项目基本信息结束 */
+
+/* 项目基本信息中的基本信息表格 */
+
+.base-container {
+  width: 100%;
+  padding: 32px;
+}
+
+.base-container .base-content {
+  width: 100%;
+  --border-color: #e2e4ec;
+  border-left: 1px solid var(--border-color);
+  border-top: 1px solid var(--border-color);
+}
+
+.base-container  .tr {
+  display: flex;
+  width: 1200px;
+  border-bottom: 1px solid var(--border-color);
+}
+
+.base-container  .tr>div {
+  flex-shrink: 0;
+  border-right: 1px solid var(--border-color);
+}
+
+.base-container  .th {
+  width: 200px;
+  height: 60px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  padding-right: 10px;
+  background: #f8f9fb;
+}
+
+.base-container  .td {
+  width: 400px;
+  height: 60px;
+  padding-left: 10px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  background: #ffffff;
+}
+
+.base-container  .th-1 {
+  width: 200px;
+  line-height: 3em;
+  padding-right: 10px;
+  background: #f8f9fb;
+  text-align: right;
+}
+
+.base-container  .td-1 {
+  width: 1000px;
+  padding: 10px;
+  background: #ffffff;
+}
+
+.base-container  .td-1>p {
+  padding: 5px;
+  margin: 0;
+}
+
+/* 项目基本信息中的内容表格 */
+.itembaseinfo-content-container {
+  width: 100%;
+  height: 100%;
+  padding-left: 32px;
+}
+
+.itembaseinfo-content-container .search-bar {
+  width: 100%;
+  height: 60px;
+}
+
+.itembaseinfo-content-container .content-area {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+  height: calc(100% - 80px);
+  width: calc(100% - 8px);
+  padding: 12px;
+  overflow-y: auto;
+
+}
+
+.itembaseinfo-content-container .table-container {
+  width: 1200px;
+  border-collapse: collapse;
+}
+
+.itembaseinfo-content-container   th {
+  background: #f5f6fa;
+}
+
+.itembaseinfo-content-container   td,
+.itembaseinfo-content-container   th {
+  border: 1px solid #d8dae3;
+  padding: 20px;
+}
+
+.itembaseinfo-content-container   tr:nth-child(odd) {
+  background: #fafafa;
+}
+
+.itembaseinfo-content-container   td[data-num]::before {
+  content: attr(data-num);
+  width: 100%;
+  font-size: inherit;
+  color: #333;
+  padding-right: 5px;
+}
+
+.itembaseinfo-content-container   td.layer-2 {
+  text-indent: 2em;
+}
+
+.itembaseinfo-content-container   td.danger {
+  color: #ff0000;
+}
+
+.itembaseinfo-item-container {
+  width: 573px;
+  height: 170px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  border: 1px solid #dddfe6;
+  --header-display: none;
+  --header-color: #999;
+}
+
+.itembaseinfo-item-container:hover {
+  --header-display: flex;
+}
+
+.itembaseinfo-item-container:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dddfe6;
+}
+
+.itembaseinfo-item-container .active {
+  border: 1px solid #ddd;
+}
+
+.itembaseinfo-item-container .action-bar {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.itembaseinfo-item-container .action-bar:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.itembaseinfo-item-container .header {
+  padding: 10px 60px 2px 20px;
+}
+
+.itembaseinfo-item-container .title {
+  font-size: 22px;
+  color: #333;
+  line-height: 2em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.itembaseinfo-item-container .body {
+  padding: 0 var(--space-size, 20px);
+  box-sizing: border-box;
+  color: #333;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.itembaseinfo-item-container .body>div {
+  height: 100px;
+}
+
+.itembaseinfo-item-container .left {
+  width: 71px;
+  background: #fafbfe;
+  border: 1px solid #f6f6f6;
+}
+
+.itembaseinfo-item-container .left img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+}
+
+.itembaseinfo-item-container .right {
+  width: calc(100% - 71px);
+  padding: 5px 0 0 20px;
+}
+
+.itembaseinfo-item-container .content {
+  height: 60px;
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
+
+.itembaseinfo-item-container .tip {
+  margin-top: 5px;
+  font-size: 18px;
+  color: #666;
+  line-height: 1.8em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 智能识别开始 */
+.ocr-container {
+  width: 100%;
+  height: 100%;
+}
+
+.ocr-container>div {
+  width: 100%;
+}
+
+.ocr-container .content-area {
+  height: calc(100% - 60px);
+  overflow-y: hidden;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.ocr-container .content-area>div {
+  width: 50%;
+  height: 100%;
+  overflow-y: hidden;
+  margin-right: 6px;
+}
+
+.ocr-container .left-side {
+  --scroll-track-color: #e2e4ec;
+}
+
+.ocr-img-box {
+  width: 100%;
+  height: 100%;
+  background-color: #e2e4ec;
+}
+
+.ocr-img-box .img-bar {
+  height: 60px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20px;
+  background: #f8f6f7;
+  font-size: 24px;
+  color: #666666;
+  box-sizing: border-box;
+  border-right: 10px solid var(--scroll-track-color);
+}
+
+.ocr-img-box .img-bar>div {
+  width: 50%;
+  flex-shrink: 0;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.ocr-img-box  .action-bar {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  color: #d5d4db;
+  border-top: 0;
+}
+
+.ocr-img-box .img-bar .action-bar .progress {
+  width: 185px;
+  height: 4px;
+  border-radius: 2px;
+  background: #d5d4db;
+  margin-right: 20px;
+  position: relative;
+  cursor: pointer;
+}
+
+.ocr-img-box .img-bar .action-bar .progress .buoy {
+  position: absolute;
+  width: 18px;
+  height: 18px;
+  border-radius: 50%;
+  border: 2px solid #c3c6ca;
+  top: 50%;
+  transform: translateY(-50%);
+  left: 0;
+  background: #fff;
+  cursor: pointer;
+}
+
+.ocr-img-box .img-bar .action-bar .icon-container {
+  cursor: pointer;
+}
+
+.ocr-img-box .img-viewer {
+  height: calc(100% - 60px);
+  width: calc(100% - 10px);
+  position: relative;
+  overflow: hidden;
+  background: #e2e4ec;
+}
+
+.ocr-img-range-box input[type=range] {
+  position: relative;
+  z-index: 12;
+  -webkit-appearance: none;
+  /*清除系统默认样式*/
+  width: 185px;
+  height: 4px;
+  border-radius: 2px;
+  background: #d5d4db;
+  background-size: 75% 100%;
+}
+
+/*拖动块的样式*/
+.ocr-img-range-box input[type=range]::-webkit-slider-thumb {
+  -webkit-appearance: none;
+  /*清除系统默认样式*/
+  width: 18px;
+  height: 18px;
+  background: #fff;
+  /*拖动块背景*/
+  border-radius: 50%;
+  /*外观设置为圆形*/
+  border: 2px solid #c3c6ca;
+}
+
+.ocr-img-range-box {
+  position: relative;
+  width: 185px;
+  display: flex;
+  align-items: center;
+  /* 垂直居中 */
+}
+
+.ocr-img-range-box .line {
+  width: 5px;
+  height: 18px;
+  background-color: #d5d4db;
+  position: absolute;
+  left: 50%;
+  transform: translateX(-50%);
+  height: 18px;
+}
+
+.ocr-img-range-box {
+  display: flex;
+  align-items: center;
+}
+
+.zoomable-img {
+  object-fit: contain;
+  transition: transform 0.3s, width 0.3s, height 0.3s;
+}
+
+.ocr-img-box .img-viewer .img-box {
+  width: 100%;
+  overflow-y: hidden;
+  background: white;
+}
+
+.ocr-img-box .img-viewer .img-box::-webkit-scrollbar {
+  width: 8px;
+  height: 8px;
+}
+
+.ocr-img-box .img-viewer .img-box::-webkit-scrollbar-thumb {
+  border-radius: 4px;
+  background: #575d6d;
+}
+
+.ocr-img-box .img-viewer .img-box::-webkit-scrollbar-track {
+  background: var(--scroll-track-color);
+}
+
+.ocr-img-box .img-viewer .img-box>img {
+  user-drag: none;
+  -webkit-user-drag: none;
+  -khtml-user-drag: none;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+  margin: 0 auto;
+  display: block;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.ocr-container .content-area .right-side {
+  overflow-y: auto;
+
+  padding: 20px;
+}
+
+.ocr-container .content-area .table-container {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.ocr-container .content-area .table-container.table-header {
+  margin-bottom: 20px;
+}
+
+.ocr-container .table-container th,
+.ocr-container .table-container td {
+  border: 1px solid #e2e4ec;
+}
+
+.ocr-container .table-container th {
+  width: 30%;
+  text-align: right;
+  font-weight: normal;
+  background: #f8f9fb;
+  padding: 15px;
+  color: #666666;
+  font-size: 16px;
+}
+
+.ocr-container .table-container td {
+  width: 70%;
+  padding: 0;
+}
+
+.ocr-container .table-container td>input {
+  width: 100%;
+  outline: none;
+  padding: 15px;
+  line-height: 1em;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+}
+
+.ocr-container .table-container td>textarea {
+  width: 100%;
+  height: 120px;
+  resize: none;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+.ocr-container .table-container td>select {
+  width: 100%;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+
+
+.ocr-container .content-box {
+  height: calc(100% - 60px);
+  overflow-y: auto;
+  padding: 20px;
+}
+
+.ocr-container .table-container {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.ocr-container .table-container th,
+.ocr-container .table-container td {
+  border: 1px solid #e2e4ec;
+}
+
+.ocr-container .table-container th {
+  width: 30%;
+  text-align: right;
+  font-weight: normal;
+  background: #f8f9fb;
+  padding: 15px;
+  color: #666666;
+  font-size: 16px;
+}
+
+.ocr-container .table-container td {
+  width: 70%;
+  padding: 0;
+}
+
+.ocr-container .table-container td>input {
+  width: 100%;
+  outline: none;
+  padding: 15px;
+  line-height: 1em;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+}
+
+.ocr-container .table-container td>textarea {
+  width: 100%;
+  height: 120px;
+  resize: none;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+.ocr-container .table-container td>select {
+  width: 100%;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+.ocr-container .table-container td>div.p {
+  font-size: 16px;
+  color: #333333;
+  padding: 20px 22px;
+}
+
+.ocr-container .table-container td>div.img {
+  height: 120px;
+  display: block;
+  padding: 8px 22px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.ocr-container .table-container td>div.img>img {
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+/* 智能识别结束 */
+/* 智能识别列表开始 */
+.ocr-list-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  position: relative;
+}
+
+.ocr-list-container>div {
+  height: 100%;
+}
+
+.ocr-list-container .left-side {
+  width: 220px;
+}
+
+.ocr-list-container .left-side .action-bar {
+  border-right: 2px solid var(--action-bar-bg);
+  height: 60px;
+  --action-bar-bg: #afb8d0;
+  --action-bar-color: #fff;
+  background: var(--action-bar-bg);
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 20px;
+  color: var(--action-bar-color);
+  font-size: 18px;
+  cursor: pointer;
+}
+
+.ocr-list-container .left-side .action-bar:hover {
+  --action-bar-bg: #242835;
+  --action-bar-color: #fff;
+}
+
+.ocr-list-container .left-side>div {
+  background: #edf1f5;
+}
+
+.ocr-list-container .left-side .content-box {
+  border-right: 2px solid #e2e4ec;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+  padding: 20px 10px;
+}
+
+.ocr-list-container .left-side  .item {
+  width: 100%;
+  height: 143px;
+  border: 1px solid #e2e4ec;
+  margin-bottom: 25px;
+  background: #f8f9fb;
+  position: relative;
+  cursor: pointer;
+  padding: 2px 0;
+}
+
+.ocr-list-container .left-side  .thumb {
+  height: 100px;
+  width: 100%;
+  overflow: hidden;
+}
+
+.ocr-list-container .left-side .thumb>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.ocr-list-container .left-side .title {
+  color: #333333;
+  font-size: 16px;
+  padding: 10px;
+}
+
+.ocr-list-container .left-side .status-tip {
+  position: absolute;
+  width: 28px;
+  height: 28px;
+  bottom: 0;
+  right: 0;
+}
+
+.ocr-list-container .left-side .status-tip.error {
+  color: #ff0000;
+}
+
+.ocr-list-container .left-side .status-tip.warn {
+  color: #ffa800;
+}
+
+.ocr-list-container .left-side .status-tip.success {
+  color: #3cb700;
+}
+
+.ocr-list-container .left-side .item.active {
+  outline: 8px solid #afb8d0;
+}
+
+.ocr-list-container .left-side .item:not(.ocr-list-container .left-side .item.active):hover {
+  outline: 15px solid #dddfe6;
+}
+
+.ocr-list-container .right-side {
+  width: calc(100% - 220px);
+}
+
+.ocr-list-container .right-side .content-box {
+  height: calc(100% - 60px);
+  overflow-y: auto;
+  padding: 20px;
+}
+
+.ocr-list-container .right-side .table-container {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.ocr-list-container .right-side .table-container.table-header {
+  margin-bottom: 20px;
+}
+
+.ocr-list-container .right-side .table-container tr.hide {
+  visibility: hidden;
+}
+
+.ocr-list-container .right-side .table-container tr.hide * {
+  padding: 0 !important;
+  margin: 0 !important;
+  border: unset !important;
+  outline: unset !important;
+}
+
+.ocr-list-container .right-side .table-container th,
+.ocr-list-container .right-side .table-container td {
+  border: 1px solid #e2e4ec;
+}
+
+.ocr-list-container .right-side .table-container th {
+  width: 200px;
+  text-align: right;
+  font-weight: normal;
+  background: #f8f9fb;
+  padding: 15px;
+  color: #666666;
+  font-size: 16px;
+}
+
+.ocr-list-container .right-side .table-container td {
+  padding: 0;
+}
+
+.ocr-list-container .right-side .table-container td:not([colspan]) {
+  width: 360px;
+}
+
+.ocr-list-container .right-side .table-container td[colspan="3"] {
+  width: calc(100% - 200px);
+}
+
+.ocr-list-container .right-side .table-container td>input {
+  width: 100%;
+  outline: none;
+  padding: 15px;
+  line-height: 1em;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+}
+
+.ocr-list-container .right-side .table-container td>textarea {
+  width: 100%;
+  height: 120px;
+  resize: none;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+.ocr-list-container .right-side .table-container td>select {
+  width: 100%;
+  outline: none;
+  border: unset;
+  color: #333333;
+  font-size: 16px;
+  padding: 15px;
+}
+
+/* 智能识别列表结束 */
+/* 成功弹窗开始 */
+.success-popup {
+  position: absolute;
+  bottom: var(--message-dialog-bottom, calc(100% + 5px));
+  right: var(--message-dialog-right, 0);
+  width: 459px;
+  height: 150px;
+  background: #ffffff;
+  border: 1px solid #ade791;
+  box-shadow: 10px 10px 5px 0px rgba(61, 187, 0, 0.3);
+  border-radius: 4px;
+  color: #333;
+  font-size: 18px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.success-popup>div.left {
+  width: 180px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.success-popup .icon {
+  width: 82px;
+  height: 82px;
+  background: #3dbb00;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  border-radius: 50%;
+  color: #fff;
+}
+
+.success-popup>.right {
+  width: calc(100% - 180px);
+}
+
+.success-popup>.right>div {
+  text-align: left;
+}
+
+.success-popup .title {
+  font-size: 36px;
+  color: #666666;
+}
+
+.success-popup .desc {
+  margin-top: 10px;
+  font-size: 24px;
+  color: #333;
+}
+
+/* 失败弹窗开始 */
+.errorDialog {
+  position: absolute;
+  left: 50%;
+  top: 50%;
+  transform: translate(-50%, -50%);
+  width: 587px;
+  height: 300px !important;
+  background: #ffffff;
+  border: 1px solid #e1adad;
+  box-shadow: 0px 10px 5px 0px rgba(236, 59, 56, 0.3);
+  border-radius: 4px;
+  color: #333;
+  font-size: 18px;
+}
+
+.errorDialog .body {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  padding: 50px 20px;
+}
+
+.errorDialog .left {
+  width: 180px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.errorDialog .icon {
+  width: 82px;
+  height: 82px;
+  background: #ec3b38;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  border-radius: 50%;
+  color: #fff;
+}
+
+.errorDialog .body>.right {
+  width: calc(100% - 180px);
+}
+
+.errorDialog .body>.right>div {
+  text-align: left;
+}
+
+.errorDialog .title {
+  font-size: 36px;
+  color: #666666;
+}
+
+.errorDialog .desc {
+  margin-top: 10px;
+  font-size: 24px;
+  color: #333;
+}
+
+.errorDialog .footer {
+  padding: 10px 40px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.errorDialog .btn {
+  cursor: pointer;
+  width: 120px;
+  height: 42px;
+  background: #ef5d0c;
+  border: 1px solid #f5904b;
+  border-radius: 4px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 15px;
+  color: #fff;
+}
+
+/* 审核开始 */
+.verify-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.verify-container>div {
+  height: 100%;
+}
+
+/* 左侧主内容区域 */
+.verify-container .left-side {
+  width: 100%; /* 默认状态下,右侧只占10px */
+  transition: width 0.3s ease;
+  position: relative;
+}
+
+.verify-container .left-side>div {
+  border-right: 2px solid #e2e4ec;
+}
+
+.verify-container  .content-box {
+  height: calc(100% - 60px * 2 - 30px);
+  padding: 20px 24px;
+  border-bottom: 1px solid #e2e4ec;
+  overflow-y: auto;
+}
+
+.verify-container .content-box>div {
+  background: #ffffff;
+  border: 1px solid #dddfe6;
+  border-radius: 4px;
+  padding: 24px;
+  position: relative;
+}
+
+.verify-container .content-box>div:not(:last-child) {
+  margin-bottom: 20px;
+}
+
+.verify-container .handle-bar {
+  position: absolute;
+  top: 1px;
+  left: 1px;
+  font-weight: bold;
+  cursor: pointer;
+}
+
+.verify-container .member-box .box-header .title {
+  color: #333;
+  font-size: 18px;
+  line-height: 1.8em;
+}
+
+.verify-container .member-box .box-body {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  gap: 6px;
+}
+
+.verify-container .box-body>div {
+  height: 112px;
+}
+
+.verify-container .avatar {
+  width: 81px;
+}
+
+.verify-container .left-side .box-body .avatar>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: contain;
+  object-fit: contain;
+}
+
+.verify-container .left-side .box-body .info {
+  width: calc(100% - 81px);
+  padding-left: 24px;
+}
+
+.verify-container .left-side .box-body .info .table {
+  padding: 5px 0 15px 0;
+}
+
+.verify-container .left-side .box-body .info .table>table {
+  border-collapse: collapse;
+}
+
+.verify-container .left-side .box-body .info .table>table td {
+  border: 1px solid #dddfe6;
+  padding: 5px 32px;
+  text-align: center;
+  color: #333;
+  font-size: 16px;
+}
+
+.verify-container .left-side .box-body .info .description {
+  color: #666;
+  font-size: 16px;
+}
+
+.verify-container .left-side .zhengshu-box .box-header .title {
+  color: #333;
+  font-size: 18px;
+  line-height: 1.8em;
+}
+
+.verify-container .left-side .zhengshu-box .box-body {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.verify-container .left-side .box-body>div {
+  height: 103px;
+}
+
+.verify-container .left-side .avatar {
+  width: 145px;
+}
+
+.verify-container .left-side .avatar>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+}
+
+.verify-container .left-side .info {
+  padding-left: 24px;
+  width: calc(100% - 145px);
+}
+
+.verify-container .left-side .p {
+  font-size: 16px;
+  color: #333;
+  padding: 5px 0 15px 0;
+}
+
+.verify-container .left-side .p>p {
+  line-height: 1.5em;
+  padding: 0;
+  margin: 0;
+}
+
+.verify-container .left-side .tip {
+  font-size: 16px;
+  color: #666666;
+}
+
+.verify-container .action-bar-1 {
+  border-top: 1px solid #e2e4ec;
+  position: absolute;
+  width: 100%;
+  bottom: 60px;
+  height: 90px;
+  background: #ffffff;
+}
+
+.verify-container .action-list {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  height: 50px;
+  padding: 0 28px;
+  gap: 28px;
+}
+
+.verify-container .action-list>.span {
+  cursor: pointer;
+}
+
+.verify-container .input-area {
+  height: 40px;
+  padding: 0 28px;
+}
+
+.verify-container .input-area>textarea,
+.verify-container .input-area>input {
+  padding: 0;
+  line-height: 40px;
+  width: 100%;
+  height: 100%;
+  resize: none;
+  font-size: 18px;
+  outline: unset;
+  border: unset;
+  background: unset;
+}
+
+.verify-container .action-bar-2 {
+  height: 50px;
+  background: #ffffff;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 10px 20px 10px 20px;
+  gap: 20px;
+  color: #999999;
+  font-size: 18px;
+}
+
+.verify-container .action-bar-2>button {
+  font-size: inherit;
+  --action-bar-bg: transparent;
+  --action-bar-color: inherit;
+  --action-bar-border: #bfc1c6;
+  background: var(--action-bar-bg);
+  border: 1px solid var(--action-bar-border);
+  color: var(--action-bar-color);
+  outline: none;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 10px;
+  padding: 5px 20px;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+.verify-container .btn-primary:hover {
+  --action-bar-bg: #242835;
+  --action-bar-border: #242835;
+  --action-bar-color: #fff;
+}
+
+.verify-container .btn-danger:hover {
+  --action-bar-bg: #f19149;
+  --action-bar-color: #fff;
+  --action-bar-border: #f19149;
+}
+
+.verify-container .right-side {
+  width: 16px; 
+  height: 100%;
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  background: transparent;
+  transition: width 0.3s ease;
+  overflow: hidden; /* 超出部分隐藏 */
+  z-index: 10001; /* 确保在左侧内容之上 */
+}
+
+.verify-container .right-side-div {
+  width: 280px;
+  overflow-y: auto;
+  background: #edf1f5;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+.verify-container .right-side-div .header {
+  border-bottom: 2px solid #e2e4ec;
+}
+
+/* 右侧边栏 - 展开状态 */
+.verify-container .right-side.expanded {
+  width: 296px;
+}
+
+.verify-container .right-side .btn-toggle::before{
+	content: "";
+    position: absolute;
+    left: -8px;
+    top: -4px;
+    width: 20px;
+    height: 20px;
+    transform-origin: 100% 100%;
+    transform: rotate(49deg);
+    z-index: 1;
+    border-left: 1px solid #d2d2d2;
+    background: #ffffff;
+}
+.verify-container .right-side .btn-toggle {
+  position: absolute;
+  bottom: 25%;
+  left: 0;
+  transform: translateY(30%);
+  width: 16px;
+  height: 16px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  z-index: 10;
+  border:1px solid #d2d2d2;
+  border-right: none;
+  border-top: none;
+  background: #ffffff;
+}
+.verify-container .right-side .icon-container{
+	background: #fff;
+	position:relative;
+	z-index: 1000;
+}
+/* 右侧内容容器 - 只在展开状态显示 */
+.verify-container .right-side-content {
+  opacity: 0;
+  transition: opacity 0.2s ease;
+  width: 100%;
+  height: 100%;
+  padding-left: 16px; /* 留出箭头区域 */
+  box-sizing: border-box;
+  position: relative;
+  z-index: 1000;
+}
+
+/* 展开状态下显示内容 */
+.verify-container .right-side.expanded .right-side-content {
+  opacity: 1;
+}
+
+.verify-nodes {
+  flex: 1;
+  overflow-y: auto;
+  padding: 20px 0;
+  margin-right: 6px;
+}
+
+.verify-nodes .group-item {
+  margin-bottom: 12px;
+  padding: 8px 0 8px 20px;
+}
+
+.verify-nodes .group-item {
+  position: relative;
+}
+/* .verify-nodes .group-item::before {
+  position: absolute;
+  content: "";
+  width: 0;
+  height: 50%;
+  border-left: 1px solid #a0a0a0;
+  top: 37px;
+  left: 30px;
+}*/
+.verify-nodes .group-item:not(:last-child)::after {
+  position: absolute;
+  content: "";
+  width: 0;
+  height: calc(100% - 20px);
+  border-left: 1px solid #a0a0a0;
+  top: 37px;
+  left: 30px;
+} 
+.verify-nodes .group-item-last-open::after {
+  position: absolute;
+  content: "";
+  width: 0;
+  height: var(--group-line-height);
+  border-left: 1px solid #a0a0a0;
+  top: 37px;
+  left: 30px;
+}
+.verify-nodes .group-item-title {
+  cursor: pointer;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+}
+
+.verify-nodes .group-item .icon {
+  color: #666666;
+  position: relative;
+}
+
+.verify-nodes .group-item .num {
+  position: absolute;
+  top: 60%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  color: #999999;
+  font-size: 14px;
+}
+
+.verify-nodes .group-item-children {
+
+  padding-left: 20px;
+}
+
+.verify-node-container {
+  padding: 16px 0;
+}
+
+.verify-node-container>.info {
+  padding: 0 10px;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  height: 60px;
+}
+
+
+.verify-node-container>.info>.avatar {
+  width: 50px;
+  height: 50px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.verify-node-container>.info>.desc {
+  width: calc(100% - 60px - 60px);
+  color: #333333;
+  font-size: 14px;
+  line-height: 1.6em;
+  padding: 0 10px;
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-end;
+}
+
+.verify-node-container>.info>.desc>div {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.verify-node-container>.info>.link {
+  width: 60px;
+}
+
+.verify-node-container>.info>.link>div {
+  padding-top: 30px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 10px;
+  color: #555c6b;
+}
+
+.verify-node-container .description {
+  /* margin-top: 5px; */
+  padding: 10px;
+}
+
+.verify-node-container .description.link {
+  position: relative;
+}
+
+.verify-node-container .description.link::before {
+  position: absolute;
+  width: 20px;
+  content: "";
+  height: 0;
+  border-bottom: 1px solid #a0a0a0;
+  top: 30px;
+  left: -10px;
+}
+
+.verify-node-container .description.link::after {
+  position: absolute;
+  width: 16px;
+  content: attr(data-num);
+  height: 16px;
+  border-radius: 50%;
+  background: #edf1f5;
+  border: 1px solid #a0a0a0;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  font-size: 12px;
+  top: 21px;
+  left: -18px;
+  z-index: 100;
+}
+
+.verify-node-container .description>div {
+  width: 100%;
+  background: #fff;
+  border-radius: 3px;
+  position: relative;
+  padding: 8px 17px;
+  color: #333333;
+  font-size: 14px;
+}
+
+.verify-node-container .description>div::before {
+  content: "";
+  width: 10px;
+  height: 10px;
+  background: #fff;
+  position: absolute;
+  left: 26px;
+  top: -5px;
+  transform: rotate(45deg);
+  border-radius: 2px;
+}
+
+.verify-node-container .time {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  color: #666666;
+  font-size: 14px;
+  padding: 0 10px;
+}
+
+/* 审核结束 */
+/* 知识库弹窗查看项目 */
+.know-item-container {
+  width: 587px;
+  height: 157px;
+  box-shadow: 2px 2px 5px #e7e8e8;
+  background: #fafbfe;
+  border-radius: 4px;
+  position: relative;
+  cursor: pointer;
+  --header-display: none;
+  --header-color: #999;
+}
+
+.know-item-container:hover {
+  --header-display: flex;
+}
+
+.know-item-container:hover::after {
+  --border-size: 8px;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  top: calc(-1 * var(--border-size));
+  left: calc(-1 * var(--border-size));
+  content: "";
+  border-radius: 4px;
+  pointer-events: none;
+  box-sizing: content-box;
+  border: var(--border-size) solid #dddfe6;
+}
+
+.know-item-container.active {
+  border: 1px solid #ddd;
+}
+
+.know-item-container .header {
+  width: 48px;
+  height: 48px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  display: var(--header-display);
+  color: var(--header-color);
+  top: 0;
+  right: 0;
+  position: absolute;
+  border-top-right-radius: 4px;
+}
+
+.know-item-container .header:hover {
+  --header-color: #fff;
+  background: #575d6d;
+}
+
+.know-item-container .body {
+  padding: 0px 25px;
+}
+
+.know-item-container .box-header {
+  height: 50px;
+  padding: 15px 0 5px 0;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.know-item-container .box-header .title {
+  width: 100%;
+  color: #333333;
+  font-size: 22px;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+}
+
+.know-item-container .box-header .title>div {
+  flex-shrink: 0;
+}
+
+.know-item-container .box-header .title .p {
+  width: calc(100% - 50px);
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.know-item-container .box-body {
+  height: 57px;
+  color: #333;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  --right-padding-left: 12px;
+  --right-width: calc(100% - 100px);
+}
+
+.know-item-container .no-thumb {
+  --right-padding-left: 0;
+  --right-width: 100%;
+}
+
+.know-item-container .left {
+  width: 100px;
+  height: 100%;
+}
+
+.know-item-container .left>img {
+  width: 100%;
+  height: 100%;
+  -o-object-fit: cover;
+  object-fit: cover;
+  display: block;
+}
+
+.know-item-container .right {
+  width: var(--right-width);
+  padding-left: var(--right-padding-left);
+}
+
+.know-item-container .right .title {
+  font-size: 16px;
+  color: #666666;
+  line-height: 24px;
+  display: -webkit-box;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
+
+.know-item-container .box-footer {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
+  height: 47px;
+}
+
+.know-item-container .box-footer>div {
+  width: 100%;
+}
+
+.know-item-container .box-footer .info {
+  margin-top: 5px;
+  font-size: 14px;
+  color: #999999;
+  line-height: 1.2em;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  gap: 20px;
+}
+
+.know-item-container .progress {
+  margin-top: 2px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  --status-color: #3172f1;
+}
+
+.know-item-container .progress.error {
+  --status-color: #ff0000;
+}
+
+.know-item-container .progress.waiting {
+  --status-color: #3172f1;
+}
+
+.know-item-container .status {
+  font-size: 12px;
+  padding-right: 1em;
+  color: var(--status-color);
+}
+
+.know-item-container .line {
+  flex: 1;
+  padding: 10px 0;
+  position: relative;
+}
+
+.know-item-container .line::after {
+  content: "";
+  background: #edf1f5;
+  width: 100%;
+  height: 2px;
+  border-radius: 1px;
+  position: absolute;
+  top: 50%;
+  left: 0;
+  transform: translateY(-50%);
+  z-index: 1;
+}
+
+.know-item-container .line>div {
+  z-index: 2;
+  width: 100%;
+  height: 2px;
+  border-radius: 1px;
+  position: absolute;
+  top: 50%;
+  left: 0;
+  transform: translateY(-50%);
+  background: var(--status-color);
+}
+
+.know-item-container .bar {
+  color: #c3c7cb;
+  padding-left: 1em;
+}
+
+/* 增加预警 */
+.editor-container {
+  width: 100%;
+  height: 100%;
+}
+
+.editor-container .content-box {
+  height: calc(100% - 60px);
+  padding: 25px 24px;
+}
+
+.editor-container .header {
+  height: 172px;
+}
+
+.editor-container .header>table {
+  border-collapse: collapse;
+}
+
+.editor-container .header th,
+.editor-container .header td {
+  border: 1px solid #e2e4ec;
+  padding: 20px;
+}
+
+.editor-container .header th {
+  width: 160px;
+  background: #f8f9fb;
+  color: #666666;
+  font-size: 16px;
+  text-align: right;
+  font-weight: normal;
+}
+
+.editor-container .header td {
+  color: var(--td-default-color, #333);
+  font-size: 16px;
+}
+
+.editor-container .desc {
+  --td-default-color: #666;
+}
+
+.editor-container .content-box .header select {
+  width: 100px;
+  font-size: inherit;
+  height: 100%;
+  outline: unset;
+  border: unset;
+  color: #999;
+}
+
+.editor-container .content-box .body {
+  height: calc(100% - 172px);
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  gap: 20px;
+}
+
+.editor-container .content-box .body>div {
+  width: 50%;
+  height: 100%;
+  border: 1px solid #e7e8e8;
+  box-shadow: 2px 3px 5px 0px rgba(0, 0, 0, 0.06);
+}
+
+.editor-container .content-box .body>div>div {
+  width: 100%;
+}
+
+.editor-container .item-header {
+  height: 60px;
+  border-bottom: 1px solid #eaeaea;
+  padding: 0 20px;
+  font-size: 22px;
+  color: #4d4d4d;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.editor-container .item-header-left {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  gap: 10px;
+}
+
+.editor-container .item-header-left .icon-container {
+  color: #989898;
+}
+
+.editor-container .item-header-right {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 5px;
+}
+
+.editor-container .item-header-right input {
+  width: 100px;
+  height: 24px;
+  border: 1px solid #eaeaea;
+  border-radius: 2px;
+  outline: none;
+  padding: 0 10px;
+}
+
+.editor-container .item-header-right .icon-container {
+  color: #c3c7cb;
+}
+
+.editor-container .item-body {
+  padding-right: 6px;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+}
+
+.editor-container .box-body {
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
+  overflow: hidden;
+  border: 1px solid #e2e4ec;
+}
+
+.editor-container .content-area {
+  width: 100%;
+}
+
+.editor-container .action-bar {
+  height: 60px;
+  color: #c3c6ca;
+  border-bottom: 1px solid #dedfdf;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+}
+
+.editor-container .action-bar .group {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: center;
+  position: relative;
+}
+
+.editor-container .action-bar .group::after {
+  content: "";
+  width: 0;
+  height: 60%;
+  top: 50%;
+  position: absolute;
+  right: 0;
+  border-right: 1px solid #efeff0;
+  transform: translateY(-50%);
+}
+
+.editor-container .action-bar .group>div {
+  width: 50px;
+  height: 60px;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.editor-container .content-area {
+  height: calc(100% - 60px);
+}
+
+.editor-container .content-area textarea {
+  width: 100%;
+  height: 100%;
+  resize: none;
+  outline: unset;
+  border: unset;
+  padding: 10px 20px;
+  font-size: 16px;
+  color: #333;
+}
+
+/* 弹窗底部按钮样式 */
+.bottom-div{
+  height: 60px;
+  background: white;
+  border-top: 1px solid #e2e4ec;
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 20px;
+  gap: 20px;
+  color: #999999;
+  font-size: 18px;
+  position: absolute;
+  width: 100%;
+  bottom: 0;
+  background: #fff !important;
+}
+
+.bottom-div button {
+  font-size: 18px;
+  --bottom-div-bg: transparent;
+  --bottom-div-color: inherit;
+  --bottom-div-border: #bfc1c6;
+  background: var(--bottom-div-bg);
+  border: 1px solid var(--bottom-div-border);
+  color: var(--bottom-div-color);
+  outline: none;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  gap: 5px;
+  padding: 5px 20px;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+.bottom-div button:hover {
+  --bottom-div-bg: #242835;
+  --bottom-div-color: #fff;
+}
+.bottom-div  .bottom-button-reject:hover{
+  --bottom-div-bg: #e65505 ;
+  --bottom-div-color: #fff;
+  --bottom-div-border: #e65505;
+}
+
+/* 下拉按钮开始 */
+.ss-drop-button {
+  height: 36px;
+  font-size: 16px;
+  color: #999;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  padding: 0 20px;
+  border-radius: 4px;
+  margin: 0;
+  /* line-height: 2em; */
+  cursor: pointer;
+  background: var(--btn-bg, unset);
+  color: var(--btn-color, #999999);
+  border: 1px solid var(--btn-border-color, #c4c7cc);
+  position: relative;
+}
+
+.ss-drop-button:hover {
+  --btn-bg: #393d51;
+  --btn-color: #fff;
+}
+
+.ss-drop-button .popup {
+  position: absolute;
+  top: calc(100% + 12px);
+  right: 0;
+  background-color: #393d51;
+  border-radius: 5px;
+  padding: 10px 4px;
+  z-index: 10;
+  height: auto;
+}
+
+.ss-drop-button .popup::before {
+  content: "";
+  position: absolute;
+  top: -12px;
+  /* 与弹窗的 top: calc(100% + 12px) 对应 */
+  left: 0;
+  right: 0;
+  height: 12px;
+  background: transparent;
+  /* 透明背景 */
+}
+
+.ss-drop-button .popup::after {
+  content: "";
+  width: 0.8em;
+  height: 0.8em;
+  background: #393d51;
+  position: absolute;
+  right: 1.5em;
+  top: -0.4em;
+  transform: rotate(45deg);
+
+}
+
+.ss-drop-button .popup div {
+  padding: 5px 15px;
+  cursor: pointer;
+  white-space: nowrap;
+}
+
+.ss-drop-button .popup div:hover {
+  background: #fffdfd;
+  color: #333;
+}
+.ss-drop-button-more::before{
+  width: 6px;
+  height: 6px;
+  content: '';
+  border-radius: 50%;
+  background-color: #8e8e8e;
+  position: absolute;
+  right: 4px;
+  top: 4px;
+}
+/* 下拉按钮结束 */
+/* 通用查询卡片下拉按钮开始 */
+.cart-list-button-popup{
+  position: absolute;
+  top: calc(100% + 8px);
+  right: -8px;
+  background-color: #393d51;
+  border-radius: 5px;
+  padding: 10px 4px;
+  z-index: 10;
+}
+.cart-list-button-popup::before {
+  content: "";
+  position: absolute;
+  top: -10px;
+  left: 0;
+  right: 0;
+  height: 10px;
+  background: transparent;
+}
+
+.cart-list-button-popup::after {
+  content: "";
+  width: 0.6em;
+  height: 0.6em;
+  background: #393d51;
+  position: absolute;
+  right: 1.7em;
+  top: -0.3em;
+  transform: rotate(45deg);
+}
+.cart-list-button-popup>div {
+  padding: 5px 15px;
+  cursor: pointer;
+  white-space: nowrap;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+}
+.cart-list-button-popup .cart-list-icon{
+  margin-right: 5px;
+  font-size: 16px;
+}
+.cart-list-button-popup>div:hover {
+  background: #fffdfd;
+  color: #333;
+}
+.cart-list-button-popup>div:hover .cart-list-icon::before{
+  color: #333333 !important;
+}
+/* 通用查询卡片下拉按钮结束 */
+
+/* 一级页面面包屑 */
+.bread-crumb{
+  display: flex;
+  align-items: center;
+  position: absolute;
+  left: 20px;
+  gap: 10px;
+  height: 100%;
+  z-index: 111;
+  color: #999999;
+}
+.bread-crumb>div{
+  cursor: pointer;
+}
+
+
+/* 日期选择器样式 */
+
+.el-date-table,.el-time-spinner__item{
+  font-size: 14px;
+}
+.custom-date-picker  .el-icon{
+  font-size: 16px;
+  color: #333;
+}
+.custom-date-picker .el-input__wrapper {
+  box-shadow: none !important;
+  display: flex;
+  align-items: center;
+}
+.custom-date-picker .el-input__inner::placeholder {
+  color: #999;
+
+}
+.custom-date-picker .el-input__inner {
+  font-size: 16px !important;
+  font-weight: normal;
+  height: 32px;
+  line-height: 33px;
+  color: #000;
+}
+.today .el-date-table-cell__text{
+  border: 1px solid #000;
+  border-radius: 50%;
+}
+.el-picker-panel__icon-btn{
+  margin-top: 0;
+}
+.el-date-picker__time-header{
+  padding: 12px 5px;
+  border-bottom: none;
+}
+.el-picker-panel__footer,.el-time-panel__footer{
+  border-top: none;
+  padding: 5px 10px 10px;
+}
+.el-button--small{
+  font-size: 14px;
+  padding: 14px 16px;
+
+}
+.el-time-panel__footer{
+  height: auto;
+  line-height: 25px;
+  display: flex;
+  justify-content: flex-end;
+}
+.el-time-panel__btn{
+  font-size: 14px;
+  height: 24px;
+  padding: 14px 16px;
+  margin:0;
+  line-height: unset;
+  display: flex;
+  align-items: center;
+}
+.el-input--small{
+  font-size: 16px;
+}
+.el-input--small .el-input__wrapper{
+  padding: 8px 7px 6px;
+}
+.jodit-container:not(.jodit_inline){
+  border: none !important;
+}
+/* 搜索区域的日期选择器 */
+.ss-search-date-picker input:focus,.el-picker-panel .el-input__inner:focus{
+  border:1px solid #c4c7cc !important;
+  outline: none;
+}
+.ss-search-date-picker .custom-date-picker  .el-icon{
+  font-size: 16px;
+  color: #333;
+}
+.ss-search-date-picker  .el-input--large .el-input__wrapper{
+  padding:0;
+}
+.ss-search-date-picker .el-input__wrapper {
+  height: 32px;
+  width: 100%;
+  padding:0;
+}
+.ss-search-date-picker .el-input__prefix, .ss-search-date-picker .el-input__suffix {
+  display: none;
+}
+.ss-search-date-picker .custom-date-picker .el-input__inner::placeholder {
+  color: #333;
+
+}
+.ss-search-date-picker .custom-date-picker .el-input__inner {
+  width: 100%;
+  font-size: 14px !important;
+  font-weight: normal;
+  height: 32px;
+  line-height: 33px;
+  font-family: 'SimHei', 'Microsoft YaHei', 'Helvetica Neue', Helvetica;
+}
+.ss-search-date-picker .el-input__inner::placeholder {
+  font-family: 'SimHei', 'Microsoft YaHei', 'Helvetica Neue', Helvetica !important;
+  color: #999999 !important;
+}
+.el-picker-panel .el-input__inner{
+  width: 100% !important;
+}

+ 814 - 0
alf/input.jsp

@@ -0,0 +1,814 @@
+<%@ page language="java" pageEncoding="UTF-8" isELIgnored="false" %>
+<%@ taglib uri="/ssTag" prefix="ss"%>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="pragma" content="no-cache">
+    <meta http-equiv="cache-control" content="no-cache">
+    <meta http-equiv="expires" content="0">
+    <!-- 在 head 标签中修改或添加 meta 标签 -->
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-eval' 'unsafe-inline' http://127.0.0.1:* http://localhost:* http://192.168.3.174:*; worker-src 'self' blob: http://192.168.3.174:*; script-src 'self' 'unsafe-eval' 'unsafe-inline' blob: http://192.168.3.174:*; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self' blob: http://192.168.3.174:*; frame-src 'self' blob:;">
+    <script src="../ss/js/base.js"></script>
+    <script type="module" src="../ss/js/validation-manager.js"></script>
+    <script type="module" src="../ss/js/validator-rules.js"></script>
+    <style type="text/css">
+        .avatar .el-form-item__content {
+          position: relative;
+        }
+  
+        .upload {
+          width: 124px;
+          height: 124px;
+          border-radius: 6px;
+          cursor: pointer;
+          position: absolute;
+          top: 0;
+          left: 0;
+          overflow: hidden;
+          text-align: center;
+          line-height: 124px;
+          font-size: 40px;
+          color: #c0c4cc;
+          background-color: rgba(0, 0, 0, 0.5);
+          opacity: 0;
+        }
+  
+        .upload:hover {
+          color: #fff;
+          opacity: 1;
+        }
+  
+        /* .icon {
+              width: 116px;
+              height: 116px;
+              border-radius: 3px;
+              float: left;
+          } */
+  
+        .icon-border {
+          background-color: rgba(243, 246, 248, 0.94);
+          border: 4px solid #fff;
+          box-shadow: inset 0 1.5px 3px 0 rgba(0, 0, 0, 0.15),
+            0 1.5px 3px 0 rgba(0, 0, 0, 0.15);
+          box-sizing: content-box;
+          margin: auto;
+          position: relative;
+        }
+      </style>
+</head>
+<body>
+    <div id="app">
+      <form class="form-container" @submit.prevent>
+        <div class="content-box fit-height-content">
+          <table class="table-container">
+            <tr>
+              <th rowspan="4">相片</th>
+              <td rowspan="4">
+                <div class="photo">
+                  <!-- 证件照 -->
+                  <ss-photo-upload
+                    v-model:url="idPhotoUrl"
+                    class="id-photo"
+                    :cropper-options="{
+                      width: 360,
+                      height: 360,
+                      aspectRatio: 1
+                    }"
+                  ></ss-photo-upload>
+
+                  <!-- 生活照 -->
+                  <ss-photo-upload
+                    v-model:url="lifePhotoUrl"
+                    class="life-photo"
+                    :cropper-options="{
+                      width: 400,
+                      height: 300,
+                      aspectRatio: 4/3
+                    }"
+                  ></ss-photo-upload>
+                </div>
+                <!-- <div class="photo">
+                  <div class="left">
+                    <div class="content">
+                      <input
+                        type="file"
+                        accept="image/*"
+                        id="iconFile"
+                        style="display: none"
+                      />
+
+                      <div class="icon" onclick="$('#iconFile').click();">
+                        <ss-icon name="user" size="140px" />
+                      </div>
+                      <div class="text">证件照</div>
+                    </div>
+                  </div>
+                  <div class="right">
+                    <div class="content">
+                      <div class="icon">
+                        <ss-icon name="photo" type="common" size="70px" />
+                      </div>
+                      <div class="text">生活照</div>
+                    </div>
+                  </div>
+                </div> -->
+              </td>
+              <th>姓名</th>
+              <td height="60">
+                <ss-input
+                  v-model="username"
+                  name="username"
+                  placeholder="请输入姓名"
+                  type="text"
+                ></ss-input>
+              </td>
+            </tr>
+
+            <tr>
+              <th>身份证类别</th>
+              <td height="60">
+                <ss-objp
+                  v-model="zhengjianType"
+                  name="zhengjianType"
+                  :opt="[{label:'请选择',value:''},{ label: '居民身份证', value: '1' },{ label: '香港特区护照或身份证', value: '6' },{ label: '澳门特区护照或身份证', value: '7' },{ label: '台湾居民来往大陆通行证', value: '8' },{ label: '外国人永久居留证', value: '10' }]"
+                  placeholder="请选择证件类别"
+                  width="300"
+                  load="objPickerLoad"
+                />
+              </td>
+              <script>
+
+
+                zhengjianTypeLoad:{
+
+                  var url='';
+                  ajax(url);
+                }
+              </script>
+            </tr>
+            <tr>
+              <th>证件号</th>
+              <td height="60">
+                <ss-input
+                  v-model="idCardNo"
+                  name="idCardNo"
+                  placeholder="请输入证件号"
+                  type="text"
+                ></ss-input>
+              </td>
+            </tr>
+            <tr>
+              <th>生日日期</th>
+              <td height="60">
+                <ss-date-picker
+                  v-model="date"
+                  name="date"
+                  type="date"
+                  placeholder="请选择生日日期"
+                  width="300px"
+                  @change="dateChange"
+                ></ss-date-picker>
+              </td>
+            </tr>
+            <tr>
+              <th>当前时间</th>
+              <td height="60">
+                <ss-date-picker
+                  v-model="datetime"
+                  name="datetime"
+                  :type="datetimeType"
+                  placeholder="请选择当前时间"
+                  width="300px"
+                  
+                ></ss-date-picker>
+              </td>
+              <th>时间</th>
+              <td height="60">
+                <ss-date-picker
+                  v-model="time"
+                  name="time"
+                  type="time"
+                  placeholder="请选择时间"
+                  width="300px"
+                ></ss-date-picker>
+              </td>
+            </tr>
+            <tr>
+              <th>英文名</th>
+              <td height="60">
+                <ss-input
+                  v-model="enName"
+                  name="enName"
+                  placeholder="请输入英文名"
+                  type="text"
+                ></ss-input>
+              </td>
+              <th>出生地</th>
+              <td height="60">
+                <div style="display: flex; width: 100%; height: 100%">
+                  <ss-hidden
+                    v-model="csdqm"
+                    name="csdqm"
+                    rule="226699"
+                  ></ss-hidden>
+                  <ss-cascader
+                    v-model="sheng"
+                    name="csdqm"
+                    placeholder="省"
+                    :opt="groups_sheng"
+                    width="200px"
+                    @change="handleCsdqProvinceChange"
+                    :level="1"
+                  ></ss-cascader>
+                  <ss-cascader
+                    v-model="shi"
+                    name="csdqm"
+                    placeholder="市"
+                    :opt="groups_shi"
+                    width="200px"
+                    @change="handleCsdqCityChange"
+                    :level="2"
+                  ></ss-cascader>
+                  <ss-cascader
+                    v-model="qu"
+                    name="csdqm"
+                    placeholder="区"
+                    :opt="groups_qu"
+                    width="200px"
+                    :level="3"
+                  ></ss-cascader>
+                </div>
+              </td>
+            </tr>
+            <tr>
+              <th>户籍所在地</th>
+              <td height="60">
+                <div style="display: flex; width: 100%; height: 100%">
+                 
+                  <ss-hidden
+                    v-model="hjzsdm"
+                    name="hjzsdm"
+                    rule="226699"
+                  ></ss-hidden>
+
+                <ss-cascader
+                  v-model="hjzsdmSheng"
+                  name="hjzsdm"
+                  placeholder="省"
+                  :opt="groups_hjzsdmSheng"
+                  width="200px"
+                  @change="handleHjzsdmProvinceChange"
+                  :level="1"
+                ></ss-cascader>
+                <ss-cascader
+                  v-model="hjzsdmShi"
+                  name="hjzsdm"
+                  placeholder="市"
+                  :opt="groups_hjzsdmShi"
+                  width="200px"
+                  @change="handleHjzsdmCityChange"
+                  :level="2"
+                ></ss-cascader>
+                <ss-cascader
+                  v-model="hjzsdmQu"
+                  name="hjzsdm"
+                  placeholder="区"
+                  :opt="groups_hjzsdmQu"
+                  width="200px"
+                  :level="3"
+                ></ss-cascader>
+              
+                </div>
+              </td>
+              
+            </tr>
+            <tr>
+              <th>专业</th>
+              <td>
+                <ss-cascader
+                  v-model="zyid"
+                  name="zyid"
+                  placeholder="请选择专业"
+                  :opt="groups_zyid"
+                  width="250px"
+                  @change="zyidChange"
+                  :level="1"
+                  mode="2"
+                ></ss-cascader>
+              </td>
+              <th>班级</th>
+              <td>
+                <ss-cascader
+                  v-model="bjid"
+                  name="bjid"
+                  placeholder="请选择班级"
+                  :opt="groups_bjid"
+                  width="250px"
+                  :level="2"
+                  mode="2"
+                ></ss-cascader>
+              </td>
+            </tr>
+            <tr>
+              <th>班级2</th>
+              <td>
+                <ss-cascader
+                  v-model="bjid2"
+                  name="bjid2"
+                  placeholder="请选择班级2"
+                  :opt="groups_bjid2"
+                  width="250px"
+                  :level="2"
+                  mode="2"
+                ></ss-cascader>
+              </td>
+              
+            </tr>
+            <tr>
+              <th>婚姻状况</th>
+              <td height="60">
+             
+                <!-- <ss-onoffbutton-array
+                  v-model="hyzk"
+                  name="hyzk"
+                  :opt="[{ label: '已婚', value: '1', width: '100px' },{ label: '未婚', value: '2', width: '100px' },]"
+                  multiple
+                /> -->
+                <!-- 多选模式 -->
+                <ss-onoffbutton
+                  v-model="hyzk"
+                  name="hyzk"
+                  label="已婚"
+                  value="1"
+                  
+                ></ss-onoffbutton>
+                <ss-onoffbutton
+                  v-model="hyzk"
+                  name="hyzk"
+                  label="未婚"
+                  value="2"
+                  
+                ></ss-onoffbutton>
+             
+                <ss-onoffbutton
+                  v-model="hyzk"
+                  name="hyzk"
+                  label="离异"
+                  value="3"
+                  
+                ></ss-onoffbutton>
+              </td>
+              <th>民族(可输入筛选)</th>
+              <td height="60">
+                <ss-objp
+                  v-model="mingzu"
+                  name="mingzu"
+                  :opt="groups"
+                  placeholder="民族"
+                  width="150"
+                  :input="true"
+                />
+              </td>
+            </tr>
+            <tr>
+              <th>邮箱</th>
+              <td height="60">
+                <ss-input
+                  v-model="email"
+                  name="email"
+                  placeholder="请输入邮箱"
+                  type="text"
+                ></ss-input>
+              </td>
+              <th>自定义校验</th>
+              <td height="60">
+                <ss-input
+                  v-model="fieldName"
+                  name="fieldName"
+                  placeholder="请输入自定义校验"
+                  type="text"
+                ></ss-input>
+              </td>
+            </tr>
+            <tr>
+              <th>
+                <div style="height: 150px">备注</div>
+              </th>
+              <td colspan="3" height="150px">
+                <div class="input">
+                  <ss-textarea name="remark" v-model="remark" />
+                </div>
+              </td>
+            </tr>
+            <tr>
+              <th>
+                <div style="height: 150px">jodit</div>
+              </th>
+              <td colspan="3" height="150px">
+                <ss-editor
+                  v-model="content"
+                  name="content"
+                  :url="contentUrl"
+                  :height="500"
+                  upload-url="/your-upload-url"
+                  :readonly="false"
+                  placeholder="请输入内容"
+                  @ready="onEditorReady"
+                  @change="onChange"
+                ></ss-editor>
+
+              </td>
+            </tr>
+            
+          </table>
+        </div>
+        <div>
+          <ss-validate err-msg="后台返回的错误" text-align="left" />
+        </div>
+        <div class="bottom-div">
+          <ss-bottom-button
+            text="取消"
+            @click="onDialogClose"
+            icon-class="bottom-div-close"
+          ></ss-bottom-button>
+          <ss-bottom-button
+            text="保存"
+            @click="onSubmit"
+            icon-class="bottom-div-save"
+          ></ss-bottom-button>
+        </div>
+      </form>
+    </div>
+    <script type="module">
+        const doCascade = async function({
+            children = [],
+            url,
+            vm,
+            prefix = 'groups_',
+            loadData = () => {},
+            value,           
+            mode = 1
+        }) {
+        try {
+            // 清空所有子级的值和选项
+            children.forEach(child => {
+            vm[child] = '';
+            // 使用字符串拼接替代模板字符串
+            vm[prefix + child] = [];
+            });
+            console.log(vm,prefix,children);
+            
+            if (loadData && value) {
+                const data = await loadData(value);
+                if (mode == '2') {
+                    children.forEach(child => {
+                    // 使用字符串拼接替代模板字符串
+                    vm[prefix + child] = data;
+                    });
+                } else {
+                    if (children.length > 0) {
+                    // 使用字符串拼接替代模板字符串
+                    vm[prefix + children[0]] = data;
+                    }
+                }
+                return;
+            }
+
+            if (url) {
+                const response = await fetch(url);
+                const data = await response.json();
+                    if (children.length > 0) {
+                        // 使用字符串拼接替代模板字符串
+                        vm[prefix + children[0]] = data;
+                    }
+                }
+            } catch (error) {
+                console.error('级联数据加载失败:', error);
+                if (children.length > 0) {
+                // 使用字符串拼接替代模板字符串
+                vm[prefix + children[0]] = [];
+                }
+            }
+        };
+      // 模拟 Ajax 请求的工具函数
+      const mockAjax = {
+        // 缓存数据,避免重复请求
+        _cache: null,
+
+        // 获取完整数据
+        async getData() {
+          if (this._cache) return this._cache;
+          const response = await fetch("../ss/js/level.json");
+          this._cache = await response.json();
+          return this._cache;
+        },
+
+        // 获取所有省份
+        async getProvinces() {
+          const data = await this.getData();
+          return data.map((item) => ({
+            label: item.name,
+            value: item.code,
+          }));
+        },
+
+        // 根据省份代码获取城市
+        async getCities(provinceCode) {
+          const data = await this.getData();
+          const province = data.find((p) => p.code === provinceCode);
+          if (!province || !province.children) return [];
+            
+            const cities = province.children
+            .filter((item) => item.city) // 确保是市级数据
+            .map((item) => ({
+              label: item.name,
+              value: item.code,
+            }));
+            
+          return cities
+        },
+
+        // 根据城市代码获取区县
+        async getDistricts(cityCode) {
+          const data = await this.getData();
+          for (const province of data) {
+            if (!province.children) continue;
+            const city = province.children.find((c) => c.code === cityCode);
+            if (city && city.children) {
+              return city.children.map((item) => ({
+                label: item.name,
+                value: item.code,
+              }));
+            }
+          }
+          return [];
+        },
+         // 模拟专业数据
+        getMajors() {
+          return new Promise((resolve) => {
+            setTimeout(() => {
+              resolve([
+                { label: '计算机科学与技术', value: '08010000' },  // 补齐8位
+                { label: '软件工程', value: '08020000' },
+                { label: '网络工程', value: '08030000' }
+              ]);
+            }, 1000);
+          });
+        },
+        // 模拟班级数据
+        getClasses(majorCode) {
+          // majorCode 会是 '08010000' 这样的格式
+          
+          const classData = {
+            '08010000': [
+              { label: '计科1班', value: '08010001' },
+              { label: '计科2班', value: '08010002' }
+            ],
+            '08020000': [
+              { label: '软件1班', value: '08020001' },
+              { label: '软件2班', value: '08020002' }
+            ],
+            '08030000': [
+              { label: '网络1班', value: '08030001' },
+              { label: '网络2班', value: '08030002' }
+            ]
+          };
+
+          return new Promise((resolve) => {
+            setTimeout(() => {
+              resolve(classData[majorCode] || []);
+            }, 1000);
+          });
+        }
+      };
+      SS.ready(function () {
+        ssVm.add("ss.commonValidator.notNull", ["username"], {
+          msgPrfx: "姓名",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["enName"], {
+          msgPrfx: "英文名",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["csdqm"], {
+          msgPrfx: "出生地",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["hjzsdm"], {
+          msgPrfx: "户籍所在地",
+        });
+        ssVm.add("ss.commonValidator.idCard", ["idCardNo"], {
+          msgPrfx: "证件号",
+          relField: "zhengjianType",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["date"], {
+          msgPrfx: "生日日期",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["content"], {
+          msgPrfx: "内容",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["zhengjianType"], {
+          msgPrfx: "证件类别",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["csd"], { msgPrfx: "出生地" });
+        ssVm.add("ss.commonValidator.notNull", ["mingzu"], { msgPrfx: "民族" });
+        ssVm.add("ss.commonValidator.notNull", ["hyzk"], {
+          msgPrfx: "婚姻状况",
+        });
+        ssVm.add("ss.commonValidator.notNull", ["remark"], { msgPrfx: "备注" });
+        // 邮箱格式验证
+        ssVm.add("ss.commonValidator.email", ["email"], {
+          msgPrfx: "邮箱",
+          required: true,
+        });
+
+        ssVm.add("ss.commonValidator.custom", ["fieldName"], {
+          msgPrfx: "字段名",
+          validate: (value) => {
+            // 返回 true/false 或者带消息的对象
+            if (value.includes("test")) {
+              return {
+                valid: false,
+                message: "不能输入test",
+              };
+            }
+            return true;
+          },
+        });
+        // 继承父页面的eventBus
+        const eventBus = window.parent.sharedEventBus;
+        function sonClose() {
+          // console.log("孙组件关闭了");
+        }
+
+        // 调用组件中的初始化方法
+        window.SS.dom.initializeFormApp({
+          el: "#app",
+          data() {
+            return {
+              date: "",
+              datetime: "",
+              time:"",
+              username: "",
+              enName: "",
+              idCardNo: "",
+              zhengjianType: "",
+              csd: "",
+              
+              mingzu: "",
+              zhengzhimianmao: "",
+              hyzk: "",
+              email: "",
+              fieldName: "",
+              remark: "",
+              visible: true,
+              idPhotoUrl: "",
+              lifePhotoUrl: "",
+              // lifePhotoUrl: "https://m.gzgs.edu.cn/skin/easy/image/default-personalPhoto.png",
+              groups: [
+                {
+                  value: "1",
+                  label: "汉族",
+                },
+                {
+                  value: "02",
+                  label: "蒙古族",
+                },
+              ],
+              reslutVisible: false,
+
+              csdqm: "",
+              sheng: "",
+              shi: "",
+              qu: "",
+              groups_sheng: [],
+              groups_shi: [],
+              groups_qu: [],
+              hjzsdm: "440105",
+              hjzsdmSheng: "",
+              hjzsdmShi: "",
+              hjzsdmQu: "",
+              groups_hjzsdmSheng: [],
+              groups_hjzsdmShi: [],
+              groups_hjzsdmQu: [],
+
+              zyid: '08010000',
+              bjid: '08010001',
+              bjid2: '',
+              groups_zyid: [],
+              groups_bjid: [],
+              groups_bjid2: []  ,
+              
+              content: '<p>初始内容</p>'
+              
+            };
+          },
+          setup() {},
+          methods: {
+            showDialog() {
+              this.visible = !this.visible;
+            },
+            onDialogClose() {
+              SS.closeDialog();
+              // eventBus.publish('inputDialog', false);
+            },
+            dateChange(value){
+              console.log(value);
+            },
+            onSubmit() {
+              console.trace("onSubmit called"); // 这会显示调用栈
+
+            },
+            // 加载省份数据
+            async loadProvinces() {
+              const provinces = await mockAjax.getProvinces();
+              this.groups_sheng = provinces;
+              this.groups_hjzsdmSheng = provinces;
+            },
+            // 加载专业数据
+            async loadMajors() {
+              this.groups_zyid = await mockAjax.getMajors();;
+            },
+            // 出生地区的处理方法
+            async handleCsdqProvinceChange(value) {
+              await doCascade({
+                children: ['shi', 'qu'],
+                value,
+                vm: this,
+                loadData: (value) => mockAjax.getCities(value),  // 使用箭头函数
+              });
+            },
+
+            async handleCsdqCityChange(value) {
+              await doCascade({
+                children: ['qu'],
+                value,
+                vm: this,
+                loadData: (value) => mockAjax.getDistricts(value),  // 使用箭头函数
+              });
+            },
+
+            // 户籍住所的处理方法
+            async handleHjzsdmProvinceChange(value) {
+                console.log("处罚了",value);
+              await doCascade({
+                children: ['hjzsdmShi', 'hjzsdmQu'],
+                value,
+                vm: this,
+                loadData: (value) => mockAjax.getCities(value),
+              });
+              console.log(this.groups_hjzsdmShi);
+            },
+
+            async handleHjzsdmCityChange(value) {
+              await doCascade({
+                children: ['hjzsdmQu'],
+                value,
+                vm: this,
+                loadData: (value) => mockAjax.getDistricts(value),
+  
+              });
+            },
+            async zyidChange(value) {
+              // this.bjid = '';
+              // this.bjid2 = '';
+              // this.groups_bjid = [];
+              // this.groups_bjid2 = [];
+              // this.groups_bjid = await mockAjax.getClasses(value);
+              // this.groups_bjid2 = await mockAjax.getClasses(value);
+              await doCascade({
+                children: ['bjid', 'bjid2'],
+                value,
+                vm: this,
+                loadData: (value) => mockAjax.getClasses(value),
+                mode:2
+              });
+            },
+            onEditorReady(editor) {
+              // console.log('编辑器初始化完成', editor);
+            },
+            onChange(content) {
+              console.log('内容变化:', content);
+            },
+          },
+          mounted() {
+            // 先加载初始数据
+            this.loadProvinces();  // 确保第一时间加载省份数据
+            this.loadMajors();
+          },
+
+          isDialogPage: true,
+        });
+        // window.SS.cropper.init({
+        //   el: $("#iconFile"),
+        //   photoSize: {
+        //     // 裁剪的图片大小,注意需要和 aspectRatio 保持统一比例
+        //     width: 360,
+        //     height: 360,
+        //   },
+        //   success: function (path) {
+        //     // 成功后的回调方法,path为裁剪后的img路径
+        //     console.log(path)
+        //   },
+        // });
+      });
+    </script>
+  </body>
+</html>

+ 5832 - 0
alf/ss-components.js

@@ -0,0 +1,5832 @@
+import { ssIcon, commonIcon } from "./icon-config.js";
+import * as IndexComponents from "./ss-index-components.js";
+import * as EchartComponents from "./ss-echarts-compnents.js";
+import { isNum, toStyleStr } from "./tools.js";
+import { EVEN_VAR } from "./EventBus.js";
+
+// import * as elements from "../lib/element-plus.js";
+(function () {
+  const {
+    createApp,
+    ref,
+    reactive,
+    watch,
+    onMounted,
+    onBeforeUnmount,
+    h,
+    computed,
+    resolveComponent,
+    watchEffect,
+    nextTick,
+    onVnodeMounted,
+    Teleport,
+    inject,
+    provide,
+  } = Vue;
+
+  // 弹窗默认遮罩z-index
+  let currentZIndex = 100;
+  //   目前已存在的弹窗
+  const topWindow = window.top;
+  topWindow.dialogInstances = topWindow.dialogInstances || [];
+  // 新建弹窗
+  function createSsDialogInstance(setting, callbackEvent) {
+    currentZIndex += 10; // 动态提升 z-index
+    const container = document.createElement("div");
+    document.body.appendChild(container);
+    const app = Vue.createApp({
+      render() {
+        return h(SsDialog, {
+          ...setting,
+          zIndex: currentZIndex,
+          onClose() {
+            document.body.removeChild(container); // 仅移除弹窗容器
+            const index = topWindow.dialogInstances.indexOf(app);
+            if (index > -1) {
+              topWindow.dialogInstances.splice(index, 1); // 移除实例
+            }
+            // 关闭后的回调
+            if (callbackEvent && typeof callbackEvent === "function") {
+              callbackEvent();
+            }
+            app.unmount(); // 仅卸载弹窗实例
+            if (container.parentNode) {
+              container.parentNode.removeChild(container); // 确保移除容器
+            }
+          },
+        });
+      },
+    });
+    topWindow.dialogInstances.push({ app, callbackEvent, container });
+    app.component("ss-mark", SsMark); // 注册 ss-mark 组件
+    app.component("ss-icon", SsIcon);
+    app.component("ss-full-style-header", SsFullStyleHeader); // 注册 ss-full-style-header 组件
+    app.mount(container);
+  }
+  // ss-breadcrumb 一级菜单页面面包屑
+  const SsBreadcrumb = {
+    name: "SsBreadcrumb",
+    props: {
+      level: {
+        type: Object,
+        default: null,
+      },
+    },
+    setup(props) {
+      const currentMenu = ref(null);
+      const folderPath = ref([]);
+      const eventBus = window.parent.sharedEventBus;
+
+      // 监听页面变化
+      onMounted(() => {
+        // 获取初始页面
+        currentMenu.value = eventBus.getState(EVEN_VAR.currentPage);
+        folderPath.value = eventBus.getState("folderPath") || [];
+
+        // 订阅页面变化
+        eventBus.subscribe(EVEN_VAR.currentPage, (page) => {
+          currentMenu.value = page;
+        });
+        eventBus.subscribe("folderPath", (path) => {
+          folderPath.value = path || [];
+        });
+      });
+      // 修改点击处理函数
+      const handlePathClick = (index) => {
+        if (props.level?.onBack) {
+          // 截取到点击的位置,后面的路径会被销毁
+          const newPath = folderPath.value.slice(0, index + 1);
+          eventBus.publish("folderPath", newPath);
+          // 返回到对应层级
+          const targetFolder = newPath[newPath.length - 1]?.folder || null;
+          props.level.onBack(targetFolder);
+        }
+      };
+      const SsCommonIcon = resolveComponent("SsCommonIcon");
+      return () =>
+          h("div", { class: "bread-crumb" }, [
+            currentMenu.value &&
+            h(
+                "div",
+                {
+                  onClick: () => {
+                    if (props.level?.onBack) {
+                      eventBus.publish("folderPath", []);
+                      props.level.onBack(null); // 返回到根目录
+                    } else {
+                      eventBus.publish(EVEN_VAR.currentPage, currentMenu.value);
+                    }
+                  },
+                },
+                currentMenu.value.label || currentMenu.value.name
+            ),
+
+            ...(folderPath.value || [])
+                .map((folder, index) => [
+                  h(SsCommonIcon, { class: "common-icon-arrow-right" }),
+                  h(
+                      "div",
+                      {
+                        class: "bread-crumb-item",
+                        onClick: () => handlePathClick(index),
+                        style: { cursor: "pointer" },
+                      },
+                      folder.title
+                  ),
+                ])
+                .flat(),
+          ]);
+    },
+  };
+
+  // ss-input form表单的输入
+  const SsInput = {
+    name: "SsInput",
+    inheritAttrs: false, // 不直接继承属性到组件根元素
+    props: {
+      name: {
+        type: String,
+        required: true,
+        default: "",
+      },
+      // 接收 v-model 绑定的值
+      errTip: {
+        type: String,
+      },
+      required: {
+        type: Boolean,
+        default: false,
+      },
+      placeholder: {
+        type: String,
+        default: "请输入",
+      },
+      defaultValue: [String, Number],
+      modelValue: [String, Number],
+    },
+    emits: ["update:modelValue", "input", "blur", "change"], // 允许更新 v-model 绑定的值
+    setup(props, { emit }) {
+      const errMsg = ref("");
+      const inputRef = ref(null);
+      const textareaRef = ref(null);
+      const inputValue = ref(props.modelValue || props.defaultValue || "");
+      const contentFloatingDiv = ref(false); // 控制浮动 DIV 的显示
+
+      const showRequired = computed(() => {
+        // 检查是否有验证规则(通过 window.ssVm 判断)
+        const hasValidationRule = window.ssVm?.validations?.has(props.name);
+
+        if (!hasValidationRule) return false;
+        if (errMsg.value) return true;
+        if (!inputValue.value) return true;
+        return false;
+      });
+
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          console.log(result);
+
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+
+      // 使用 watch 监听 props.errTip 和 props.modelValue 的变化
+      watch(
+          () => props.errTip,
+          (newVal) => {
+            errMsg.value = newVal;
+          },
+          { immediate: true }
+      );
+      watch(
+          () => props.modelValue,
+          (newVal) => {
+            inputValue.value = newVal;
+          }
+      );
+
+      // 挂载时的逻辑
+      onMounted(() => {
+        errMsg.value = props.errTip;
+        inputValue.value = props.modelValue || props.defaultValue || "";
+      });
+      // 计算并调整textarea的高度
+      const adjustHeight = () => {
+        nextTick(() => {
+          const textarea = textareaRef.value;
+          if (!textarea) return;
+          // 重置高度以获得正确的scrollHeight
+          textarea.style.height = "auto";
+          // 计算新高度
+          const maxHeight =
+              parseInt(getComputedStyle(textarea).lineHeight, 10) * 5; // 假设lineHeight是单行高度
+          const newHeight = Math.min(textarea.scrollHeight, maxHeight);
+          textarea.style.height = `${newHeight}px`;
+        });
+      };
+      // 定义事件处理函数
+      const onInput = (event) => {
+        const newValue = event.target.value;
+        inputValue.value = newValue;
+        emit("update:modelValue", newValue);
+        validate(); // 输入时验证
+        nextTick(() => {
+          contentFloatingDiv.value =
+              inputRef.value.scrollWidth > inputRef.value.offsetWidth;
+        });
+        adjustHeight();
+      };
+      const onFocus = (event) => {
+        nextTick(() => {
+          contentFloatingDiv.value =
+              inputRef.value.scrollWidth > inputRef.value.offsetWidth;
+        });
+        adjustHeight();
+      };
+
+      // 失去焦点时进行验证
+      const onBlur = (event) => {
+        emit("blur", event.target);
+        validate(); // 失焦时验证
+        nextTick(() => {
+          // 如果焦点不在 input 或 textarea 上,则隐藏浮动 div
+          if (!document.activeElement.classList.contains("input-control")) {
+            contentFloatingDiv.value = false;
+          }
+        });
+      };
+      const onChange = (event) => {
+        inputValue.value = event.target.value || "";
+        emit("change", inputValue.value);
+      };
+      const onMouseover = (event) => {
+        nextTick(() => {
+          // setTimeout(contentFloatingDiv.value = true, 500)
+        });
+      };
+      const onMouseleave = (event) => {
+        // contentFloatingDiv.value = false
+      };
+      return {
+        errMsg,
+        inputValue,
+        showRequired,
+        onInput,
+        onBlur,
+        onChange,
+        onMouseover,
+        onMouseleave,
+        contentFloatingDiv,
+        inputRef,
+        textareaRef,
+        onFocus,
+      };
+    },
+    render() {
+      return h("div", { class: "input" }, [
+        h("div", { class: "input-container" }, [
+          h("div", { class: "input" }, [
+            h("input", {
+              ref: "inputRef",
+              class: "input-control",
+              name: this.name,
+              value: this.inputValue,
+              onInput: this.onInput,
+              onFocus: this.onFocus,
+              onBlur: this.onBlur,
+              onChange: this.onChange,
+              placeholder: this.placeholder,
+              onMouseover: this.onMouseover, // 监听鼠标悬停
+              onMouseleave: this.onMouseleave, // 监听鼠标离开
+              ...this.$attrs,
+              autocomplete: "off",
+            }),
+            // this.showRequired ? h("div", { class: "required" }) : null,
+          ]),
+          this.contentFloatingDiv || ""
+              ? h("div", { class: "floating-div" }, [
+                h("textarea", {
+                  ref: "textareaRef",
+                  class: "input-control",
+                  value: this.inputValue,
+                  onInput: this.onInput,
+                  onBlur: this.onBlur,
+                  onFocus: this.onFocus,
+                  onMouseover: this.onMouseover, // 监听鼠标悬停
+                  onMouseleave: this.onMouseleave, // 监听鼠标离开
+                  autocomplete: "off",
+                  onVnodeMounted: (vnode) => {
+                    vnode.el.focus();
+                  },
+                }),
+              ])
+              : null,
+          // this.errMsg ? h(SsValidate, { errMsg: this.errMsg }) : null,
+        ]),
+      ]);
+    },
+  };
+  // ss-normal-input 登录输入
+  const SsLoginInput = {
+    name: "SsLoginInput",
+    inheritAttrs: false,
+    props: {
+      errTip: {
+        type: String,
+      },
+
+      type: {
+        type: String,
+        default: "text",
+      },
+      required: {
+        type: Boolean,
+        default: false,
+      },
+      placeholder: {
+        type: String,
+        default: "请输入",
+      },
+      name: {
+        type: String,
+        default: "",
+      },
+      defaultValue: [String, Number],
+      modelValue: [String, Number],
+    },
+    emits: ["update:modelValue", "input", "blur", "change"], // 允许更新 v-model 绑定的值
+    setup(props, { emit }) {
+      const errMsg = ref("");
+      const inputRef = ref(null);
+      const textareaRef = ref(null);
+      const inputValue = ref(props.modelValue || props.defaultValue || "");
+
+      // 使用 watch 监听 props.errTip 和 props.modelValue 的变化
+      watch(
+          () => props.errTip,
+          (newVal) => {
+            errMsg.value = newVal;
+          },
+          { immediate: true }
+      );
+      watch(
+          () => props.modelValue,
+          (newVal) => {
+            inputValue.value = newVal;
+          }
+      );
+
+      // 挂载时的逻辑
+      onMounted(() => {
+        errMsg.value = props.errTip;
+        inputValue.value = props.modelValue || props.defaultValue || "";
+      });
+
+      // 定义事件处理函数
+      const onInput = (event) => {
+        const newValue = event.target.value;
+        inputValue.value = newValue;
+        emit("update:modelValue", newValue);
+      };
+      return { inputValue, onInput, inputRef, textareaRef };
+    },
+    render() {
+      return h("div", { class: "input" }, [
+        h("div", { class: "input-container" }, [
+          h("div", { class: "input" }, [
+            h("input", {
+              ref: "inputRef",
+              class: "input-control",
+              name: this.name,
+              value: this.inputValue,
+              onInput: this.onInput,
+              type: this.type,
+              placeholder: this.placeholder,
+              required: this.required,
+              ...this.$attrs,
+              autocomplete: "off",
+            }),
+            this.required ? h("div", { class: "required" }) : null,
+          ]),
+        ]),
+      ]);
+    },
+  };
+  // ss-login-button
+  const SsLoginButton = {
+    name: "SsLoginButton",
+    inheritAttrs: false,
+    props: {
+      class: {
+        type: String,
+        default: "",
+      },
+      text: {
+        type: String,
+        default: "",
+      },
+      type: {
+        type: String,
+        default: "button",
+      },
+    },
+    emits: ["click"],
+    setup(props, { emit }) {
+      // 定义事件处理函数
+      const onClick = (event) => {
+        // 发射一个 'click' 事件,你可以传递所需的参数
+        emit("click", event);
+      };
+
+      return { props, onClick };
+    },
+    render() {
+      const SsIcon = resolveComponent("ss-icon");
+      const SsLoginIcon = resolveComponent("ss-login-icon");
+      return h(
+          "button",
+          { class: "login-button", type: this.type, onClick: this.onClick },
+          [
+            h("span", [h(SsLoginIcon, { class: this.class })]),
+            h("span", {}, this.text),
+          ]
+      );
+    },
+  };
+  // ss-objp 下拉选择
+  const SsObjp = {
+    name: "SsObjp",
+    inheritAttrs: false,
+    props: {
+      filter: {
+        type: String,
+        required: false,
+      },
+      cb: {
+        type: String,
+        required: true,
+      },
+      url: {
+        type: String,
+        required: true,
+      },
+      name: {
+        type: String,
+        required: true,
+      },
+      width: {
+        type: String,
+        default: "100%",
+      },
+      placeholder: {
+        type: String,
+        default: "请选择",
+      },
+      inp: {
+        type: Boolean,
+        default: false,
+      },
+      opt: {
+        type: Array,
+        default: () => [],
+      },
+      errTip: String,
+      defaultValue: [String, Number],
+      modelValue: [String, Number],
+      direction: {
+        type: String,
+        default: "bottom",
+      },
+    },
+    emits: ["update:modelValue", "input", "blur", "change"],
+    setup(props, { emit }) {
+      const canInput = props.inp;
+      const errMsg = Vue.ref(props.errTip);
+      const selectItem = Vue.ref({});
+      let inputText = Vue.ref(""); // 用于存储输入框的文本
+      const popupWinVisible = Vue.ref(false);
+
+      const filteredOptions = Vue.ref(props.opt);
+      const popupDirection = Vue.ref("bottom");
+
+      // const showRequired = Vue.computed(() => {
+      //   const hasValidationRule = window.ssVm?.validations?.has(props.name);
+      //   if (!hasValidationRule) return false;
+      //   if (errMsg.value) return true;
+      //   if (!selectItem.value?.value) return true;
+      //   return false;
+      // });
+
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          // console.log("validate", window.ssVm.validateField(props.name));
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+
+      //在objPicker界面,选中value对应的项
+      const updateSelectItem = () => {
+        // console.log(props.opt);
+        const item = props.opt.find((it) => it.value === props.modelValue);
+        if (item) {
+          selectItem.value = item;
+          inputText.value = item.label;
+        } else {
+          selectItem.value = { label: "", value: "" };
+          inputText.value = "";
+        }
+        // validate();
+      };
+
+      Vue.watch(
+          () => props.errTip,
+          (newVal) => {
+            errMsg.value = newVal;
+          }
+      );
+
+      Vue.watch(() => props.modelValue, updateSelectItem, { immediate: true });
+      Vue.watch(
+          () => props.opt,
+          (newVal) => {
+            updateSelectItem();
+            filteredOptions.value = [...newVal];
+            // console.log("filteredOptions", filteredOptions.value);
+          }
+      );
+
+      //初始化objPicker在页面刚打开时的默认值
+      async function initDefaultValue() {
+        try {
+          if (props.url && props.cb && props.modelValue) {
+            const objectPickerParam = { input: props.inp, codebook: props.cb };
+            const objectPickerParamStr = JSON.stringify(objectPickerParam);
+
+            const params = new URLSearchParams();
+            params.append("objectpickerparam", objectPickerParamStr);
+            params.append("objectpickertype", "2");
+            params.append("objectpickervalue", props.modelValue); //需回显的值
+
+            axios
+                .post(props.url, params, {
+                  headers: {
+                    "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                  },
+                })
+                .then((response) => {
+                  // alert(JSON.stringify(response.data));
+
+                  if ("timeout" == response.data.statusText) {
+                    alert("网络超时!");
+                    return;
+                  }
+
+                  if (response.data.result) {
+                    const keys = Object.keys(response.data.result);
+                    if (keys.length === 1) {
+                      let code = keys[0];
+                      let desc = response.data.result[keys[0]];
+                      if (props.opt)
+                        props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
+                      else {
+                        props.opt = [];
+                      }
+                      props.opt.push({ label: desc, value: code });
+                      updateSelectItem();
+
+                      // alert('props.opt:'+JSON.stringify(props.opt));
+                    }
+                  }
+                });
+          }
+        } catch (error) {
+          // callback(null, error.message); // 失败回调,传递错误
+        }
+      }
+
+      // Vue.onMounted(updateSelectItem);
+
+      const doSelectItem = (item) => {
+        emit("update:modelValue", item.value);
+        selectItem.value = item;
+        inputText.value = item.label;
+        hidePopup();
+        nextTick(() => {
+          console.log(item.value + "@@@props.modelValue:" + props.modelValue);
+          validate();
+          if (window.ssVm) {
+            // 遍历所有验证规则,找到依赖当前字段的规则
+            for (const [field, rules] of window.ssVm.validations.entries()) {
+              for (const rule of rules) {
+                if (rule.opt?.relField === props.name) {
+                  // console.log("Found dependent field:", field); // 调试日志
+                  window.ssVm.validateField(field);
+                }
+              }
+            }
+          }
+        });
+      };
+
+      //可录入的objPicker,更新下拉菜单选项
+      async function updateOptionBYInputText(inpTxt) {
+        try {
+          let objectPickerParam;
+          let url = props.url;
+
+          if (props.url && props.cb) {
+            //如果有定义过滤器
+            if (props.filter) {
+              //包含HTML实体的JSON字符串转为JSON对象,如原字符串是{&quot;dwid&quot;:&quot;88&quot;},注意key也必需用单引号包着
+              const decodedString = props.filter.replace(/&quot;/g, '"'); // 转换为: {"dwid":"88"}
+              objectPickerParam = JSON.parse(decodedString); // 转为json对象
+              objectPickerParam["input"] = props.inp;
+              objectPickerParam["codebook"] = props.cb;
+
+              const filterObj = JSON.parse(decodedString); // 转为json对象
+              for (let k in filterObj) {
+                let v = filterObj[k];
+                url += "&" + k + "=" + v;
+              }
+
+              // alert(url);
+            } else {
+              objectPickerParam = { input: props.inp, codebook: props.cb };
+            }
+
+            const objectPickerParamStr = JSON.stringify(objectPickerParam);
+            const params = new URLSearchParams();
+            params.append("objectpickerparam", objectPickerParamStr);
+            params.append("objectpickertype", "1");
+            if (props.inp && props.inp === "true") {
+              params.append("objectpickersearchAll", 0); //只查录入的值
+              params.append("objectpickerinput", inpTxt); //录入的值
+            } else {
+              params.append("objectpickersearchAll", 1);
+            }
+
+            axios
+                .post(url, params, {
+                  headers: {
+                    "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                  },
+                })
+                .then((response) => {
+                  if ("timeout" == response.data.statusText) {
+                    alert("网络超时!");
+                    return;
+                  }
+
+                  if (response.data.result) {
+                    const keys = Object.keys(response.data.result);
+                    // console.log("params:"+params+"@@response.data:"+JSON.stringify(response.data));
+                    if (keys.length > 0) {
+                      if (props.opt)
+                        props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
+                      else {
+                        props.opt = [];
+                      }
+                      for (let k in response.data.result) {
+                        props.opt.push({
+                          label: response.data.result[k],
+                          value: k,
+                        });
+                      }
+
+                      // console.log('###inpTxt:'+inpTxt+';');
+                      if (
+                          props.inp &&
+                          props.inp === "true" &&
+                          inpTxt.length > 0
+                      ) {
+                        //对于可录入的,用已录入的值作过滤
+
+                        filteredOptions.value = props.opt.filter((option) =>
+                            option.label
+                                .toLowerCase()
+                                .includes(inputText.value.toLowerCase())
+                        );
+                        filteredOptions.value.unshift({ label: "", value: "" });
+
+                        // console.log('###做了过滤:'+inputText.value.toLowerCase()+';');
+                      } else {
+                        filteredOptions.value = props.opt;
+                        filteredOptions.value.unshift({ label: "", value: "" });
+                      }
+
+                      if (!popupWinVisible.value) {
+                        popupWinVisible.value = true; // 确保下拉框在输入时打开
+                      }
+
+                      console.log("props.opt11:" + JSON.stringify(props.opt));
+                    }
+                  }
+                });
+          }
+        } catch (error) {
+          // callback(null, error.message); // 失败回调,传递错误
+        }
+      }
+
+      // 计算弹出方向的方法
+      const calculatePopupDirection = () => {
+        // 1. 获取select容器元素
+        const selectEl = document
+            .querySelector(`[name="${props.name}"]`)
+            ?.closest(".select-container");
+        if (!selectEl) return;
+
+        // 2. 获取位置信息
+        const selectRect = selectEl.getBoundingClientRect();
+        const viewportHeight = window.innerHeight;
+
+        // 3. 简单判断:如果下方剩余空间小于300px就向上弹出
+        const spaceBelow = viewportHeight - selectRect.bottom;
+
+        // 调试信息
+        // console.log('空间判断:', {
+        //   elementBottom: selectRect.bottom,
+        //   viewportHeight,
+        //   spaceBelow,
+        //   willPopUp: spaceBelow < 300,
+        //   popupDirection: popupDirection.value
+        // });
+
+        // 4. 设置方向
+        popupDirection.value = spaceBelow < 300 ? "top" : "bottom";
+      };
+
+      //点击下拉菜单的文本区域时,会触发的方法
+      function togglePopup() {
+        //可录入的objPicker,更新下拉菜单选项
+        updateOptionBYInputText(inputText.value);
+        // popupWinVisible.value = !popupWinVisible.value;
+        Vue.nextTick(() => {
+          calculatePopupDirection();
+        });
+      }
+
+      const hidePopup = () => {
+        popupWinVisible.value = false;
+      };
+
+      //点击下拉菜单的三角形时,会触发的方法
+      const suffixClick = () => {
+        //可录入的objPicker,更新下拉菜单选项
+        updateOptionBYInputText("");
+        // popupWinVisible.value = !popupWinVisible.value;
+        Vue.nextTick(() => {
+          calculatePopupDirection();
+        });
+        console.log("点三角");
+      };
+
+      //可录入的objPicker,录入项变化时,会触发
+      async function handleInputChange(event) {
+        inputText.value = event.target.value;
+        if (!inputText.value) {
+          inputText.value = "";
+        }
+
+        //可录入的objPicker,更新下拉菜单选项
+        updateOptionBYInputText(inputText.value);
+
+        // filteredOptions.value = props.opt.filter((option) =>
+        //     option.label.toLowerCase().includes(inputText.value.toLowerCase())
+        // );
+        // if (!popupWinVisible.value) {
+        //   popupWinVisible.value = true; // 确保下拉框在输入时打开
+        // }
+      }
+      Vue.onMounted(() => {
+        initDefaultValue();
+        window.addEventListener("resize", calculatePopupDirection);
+      });
+      Vue.onUnmounted(() => {
+        window.removeEventListener("resize", calculatePopupDirection);
+      });
+
+      return {
+        errMsg,
+        selectItem,
+        inputText,
+        canInput,
+        filteredOptions,
+        popupWinVisible,
+        popupDirection,
+        suffixClick,
+        togglePopup,
+        hidePopup,
+        doSelectItem,
+        handleInputChange,
+      };
+    },
+
+    template: `
+      <div class="input" style="position: relative" :style="{width: width}">
+        <div class="select-container" @mouseleave="hidePopup">
+          <div class="input" @click="togglePopup">
+            <input 
+              type="hidden"
+              :name="name"
+              :value="selectItem.value"
+              .value="selectItem.value" 
+            />
+            <input
+              v-model="inputText"
+              @input="handleInputChange"
+              v-if="canInput"
+              :placeholder="placeholder"
+              
+            />
+            
+            <input
+              v-else
+              :placeholder="placeholder"
+              :value="selectItem.label"
+              
+              disabled
+              style="pointer-events: none;"
+            />
+           
+            <div class="suffix" @click.stop="suffixClick">
+              <ss-form-icon :class="popupWinVisible ? 'form-icon-transform-select select' : 'form-icon-select'" />
+              
+            </div>
+          </div>
+         
+            
+          <div v-show="popupWinVisible" class="popup-win" :class="popupDirection">
+            <div v-if="opt && opt.length && filteredOptions.length > 0" class="popup-content">
+              <div class="content-area">
+                <div v-for="(item, index) in filteredOptions" :key="index" @click="doSelectItem(item)" :class="{ active: item.value === selectItem.value }">
+                  <span class="check-icon">
+                   
+                    <ss-form-icon class="form-icon-select-checked" />
+                  </span>
+                  <span>{{ item.label }}</span>
+                </div>
+              </div>
+            </div>
+            <div v-else class="popup-content"><div class="content-area"><div class="content-area"> <span>无选项</span></div></div></div>
+          </div>
+        </div>
+      </div>
+
+    `,
+  };
+  // ss-hidden 隐藏字段组件
+  const SsHidden = {
+    name: "SsHidden",
+    props: {
+      modelValue: String,
+      name: {
+        type: String,
+        required: true,
+      },
+      rule: {
+        type: String,
+        required: true,
+      },
+
+      param: {
+        type: String,
+        required: true,
+      },
+      url: {
+        type: String,
+        required: true,
+      },
+    },
+    emits: ["update:modelValue"],
+
+    setup(props, { emit }) {
+      const errMsg = Vue.ref("");
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          console.log("validate", window.ssVm.validateField(props.name));
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+      Vue.onMounted(() => {
+        /**
+         * 初始化级联菜单值初始值思路:
+         * 1. 带隐藏字段(即带编码规则)的级联菜单
+         *  在隐藏字段这,可以取到要回显的值和编码规则,从而计算出各级下拉菜单要回显的值。
+         *  然后通过ajax取各级级联菜单的值回显。
+         *  2. 不带隐藏字段的级联,只能在各个下拉菜单的setup事件中通过ajax取回显值回显
+         */
+
+        // 当同组级联下拉菜单选中值变化时,会调用本隐藏字段下面这方法设置隐藏字段值
+        window.addEventListener(
+            "cascader-setHiddenVal-" + props.name,
+            (event) => {
+              const { value } = event.detail;
+              emit("update:modelValue", value);
+              console.log(value);
+              setTimeout(() => {
+                validate();
+              }, 50);
+            }
+        );
+
+        // 如果有初始值,触发回显过程
+        if (props.modelValue) {
+          console.log("级联隐藏字段,开始回显,初始值:", props.modelValue);
+          triggerCascaderEcho(props.modelValue);
+          validate();
+        }
+      });
+
+      // 触发级联回显
+      const triggerCascaderEcho = (code) => {
+        /**
+         * 开始回显,初始值: 440304
+         * 解析后的所有值: Array(3)0: "440000"1: "440300"2: "440304"length: 3[[Prototype]]: Array(0)
+         */
+        const values = parseHiddenCodeForAll(code, props.rule);
+        console.log("解析后的所有值:", values);
+
+        // 转换为 JSON 对象
+        // const paramObj = JSON.parse(props.param);
+        const paramObj = props.param;
+        let selectArr = paramObj.fieldOrd; //保存本组级联菜单项的数组,如:['hksheng','hkshi','hkxian']
+        if (selectArr.length != values.length) {
+          // alert('属性'+props.name+'的值'+code+'与级联菜单中下拉菜单的数目不匹配!');
+          return;
+        }
+
+        // 按顺序触发回显,并增加延迟确保数据加载
+        /**
+         * 通过隐藏字段的setup事件,
+         * 循环遍历各级下拉菜单,并触发定义在下拉菜单中的'cascader-echo'事件,
+         * 在此事件中完成每个下拉菜单回显值操作(只取当前要回显的键值对显示,
+         * 下拉菜单所有的值,在点击下拉菜单时,才通过ajax取)。
+         */
+        values.forEach((value, index) => {
+          if (value) {
+            setTimeout(() => {
+              let upperVal = undefined;
+              if (index != 0) {
+                upperVal = values[index - 1];
+              }
+
+              const echoEvent = new CustomEvent(
+                  "cascader-echo-" + selectArr[index],
+                  {
+                    detail: {
+                      name: props.name,
+                      value: value,
+                      // level: index + 1,
+                      isAuto: true, // 标记为自动回显
+                      upperVal: upperVal,
+                    },
+                  }
+              );
+
+              console.log(props.name + "--upperValue:" + upperVal);
+
+              window.dispatchEvent(echoEvent);
+            }, index * 500); // 每级增加500ms延迟
+          }
+        });
+      };
+
+      // 解析所有级别的代码
+      const parseHiddenCodeForAll = (code, rule) => {
+        if (!code || !rule) return [];
+
+        // 获取规则中每段的长度
+        const segments = [];
+        let currentChar = rule[0];
+        let currentLength = 1;
+
+        for (let i = 1; i < rule.length; i++) {
+          if (rule[i] === currentChar) {
+            currentLength++;
+          } else {
+            segments.push(currentLength);
+            currentChar = rule[i];
+            currentLength = 1;
+          }
+        }
+        segments.push(currentLength);
+
+        // 解析每一级的值
+        const values = [];
+        let position = 0;
+
+        segments.forEach((length, index) => {
+          const value = code
+              .substring(0, position + length)
+              .padEnd(rule.length, "0");
+          values.push(value);
+          position += length;
+        });
+
+        return values;
+      };
+      watchEffect(() => {});
+      return {};
+    },
+    template: `<input type="hidden" :name="name" :value="modelValue">`,
+  };
+  // ss-cascader 级联选择器
+  const SsCcp = {
+    name: "SsCcp",
+    inheritAttrs: false,
+    props: {
+      modelValue: String,
+
+      name: {
+        type: String,
+        required: true,
+      },
+      level: {
+        type: Number,
+        required: true,
+      },
+      opt: {
+        type: Array,
+        default: () => [],
+      },
+      placeholder: {
+        type: String,
+        default: "请选择",
+      },
+      width: {
+        type: String,
+        default: "150px",
+      },
+      direction: {
+        type: String,
+        default: "bottom",
+      },
+      mode: {
+        type: String,
+        default: "1",
+      },
+
+      //级联菜单配置参数,如果是数组,则代表本下拉菜单是多套级联菜单共用的第一级菜单。如果是对象,则只有一套级联菜单用此下拉菜单。
+      param: {
+        type: String,
+        required: true,
+      },
+      //向后台拿数据的url
+      url: {
+        type: String,
+        required: true,
+      },
+    },
+    emits: ["update:modelValue", "change"],
+
+    setup(props, { emit }) {
+      // alert('级联菜单初始化:'+props.name+':--:'+props.modelValue);
+      const selectItem = Vue.ref({ label: props.placeholder, value: "" });
+      const popupWinVisible = Vue.ref(false);
+      const isAutoEcho = Vue.ref(false); // 用于标记是否是自动回显
+      const upperValue = Vue.ref(""); //上级下拉菜单当前值,在初始化下拉菜单默认值时,和上级下拉菜单的值变化时,修改此upperValue变量
+      const popupDirection = Vue.ref("bottom");
+
+      //有隐藏字段的下拉菜单,加载菜单项并展开事件
+      // 被上级下拉菜单选中值后,触发本下拉菜单刷新菜单项并弹出显示
+      window.addEventListener("cascader-open-" + props.name, async (event) => {
+        const { upperVal } = event.detail;
+        upperValue.value = upperVal;
+        console.log(
+            "22props.name:" +
+            props.name +
+            ",22props.upperValue:" +
+            upperValue.value
+        );
+
+        selectItem.value = ""; //清除本下拉菜单当前选中的值
+        emit("update:modelValue", ""); //通知父级
+
+        //清空下拉菜单,并设置第一项的值为placeholder
+        clearAndInit1stOpt();
+
+        //下个下拉菜单名
+        let nextSelName = getNextSel(props.name, props.param.fieldOrd);
+        if (nextSelName) {
+          //清下个下拉菜单选中值和选项
+          event = new CustomEvent("cascader-cleanOpt-" + nextSelName, {
+            detail: {},
+          });
+          window.dispatchEvent(event);
+        }
+
+        showPopup();
+      });
+
+      //设置mode2的下级下拉菜单的上级菜单当前值
+      function setNextSelectUpperValue() {
+        //设置下级菜单的上级菜单当前值upperValue
+        let paramArr = undefined;
+        if (Array.isArray(props.param)) {
+          paramArr = props.param;
+        } else {
+          paramArr = [];
+          paramArr.push(props.param);
+        }
+
+        for (const oneParam of paramArr) {
+          //下个下拉菜单名
+          const nextSelName = getNextSel(props.name, oneParam.fieldOrd);
+          if (nextSelName) {
+            setTimeout(() => {
+              const openNextEvent = new CustomEvent(
+                  "cascade-setUpperVal-" + nextSelName,
+                  {
+                    detail: {
+                      upperVal: props.modelValue,
+                    },
+                  }
+              );
+              window.dispatchEvent(openNextEvent);
+            }, 100);
+          }
+        } // end for
+      }
+
+      // 把上级 级联下拉菜单的值,设置进本组件的事件
+      window.addEventListener("cascade-setUpperVal-" + props.name, (event) => {
+        // alert('props.name:'+props.name+',props.upperValue:'+event.detail.upperVal);
+        const { upperVal } = event.detail;
+        upperValue.value = upperVal;
+
+        // console.log('props.name:'+props.name+',props.upperValue:'+upperValue.value);
+      });
+
+      //清空下拉菜单,并设置第一项的值为空
+      function clearAndInit1stOpt() {
+        if (props.opt)
+          props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
+        else {
+          props.opt = [];
+        }
+        props.opt.push({ label: "", value: "" });
+      }
+
+      //获取下一级下拉菜单,如果下一级下拉菜单不存在,则返回undefined
+      function getNextSel(selName, selNameArr) {
+        // 检查参数有效性
+        if (!Array.isArray(selNameArr) || selNameArr.length === 0) {
+          return undefined;
+        }
+
+        // 查找当前元素的索引
+        const currentIndex = selNameArr.indexOf(selName);
+
+        // 如果元素不存在或已经是最后一个元素,返回undefined
+        if (currentIndex === -1 || currentIndex === selNameArr.length - 1) {
+          return undefined;
+        }
+
+        // 返回下一个元素
+        return selNameArr[currentIndex + 1];
+      }
+
+      // 处理选择事件
+      const doSelectItem = (item) => {
+        selectItem.value = item;
+        emit("update:modelValue", item.value); //修改本下拉菜单在vue中保存的值
+
+        // alert('item.value:'+item.value);
+        if (props.mode === "1") {
+          // mode 1 模式:修改隐藏字段值
+
+          let event = new CustomEvent(
+              "cascader-setHiddenVal-" + props.param.combField,
+              {
+                detail: {
+                  value: item.value,
+                },
+              }
+          );
+          window.dispatchEvent(event);
+        }
+        emit("change", item.value); //触发配置的change方法
+
+        //设置下级菜单的上级菜单当前值upperValue
+        let paramArr = undefined;
+        if (Array.isArray(props.param)) {
+          paramArr = props.param;
+        } else {
+          paramArr = [];
+          paramArr.push(props.param);
+        }
+
+        for (const oneParam of paramArr) {
+          //下个下拉菜单名
+          const nextSelName = getNextSel(props.name, oneParam.fieldOrd);
+          if (nextSelName) {
+            setTimeout(() => {
+              const openNextEvent = new CustomEvent(
+                  "cascader-open-" + nextSelName,
+                  {
+                    detail: {
+                      upperVal: item.value,
+                    },
+                  }
+              );
+              window.dispatchEvent(openNextEvent);
+            }, 100);
+          }
+        } // end for
+
+        hidePopup();
+
+        //下个下拉菜单名
+        // let nextSelName = getNextSel(props.name, props.param.fieldOrd);
+        // if(nextSelName){
+        //   // //设置下一级下拉菜单中保存的本下拉菜单值(upperValue)
+        //   // event = new CustomEvent('cascade-setUpperVal-'+nextSelName, {
+        //   //   detail: {
+        //   //     value: item.value
+        //   //   }
+        //   // });
+        //   // window.dispatchEvent(event);
+        //
+        //   //触发下一级下拉菜单,重新初始化下拉菜单项并弹出显示
+        //   event = new CustomEvent('cascader-open-' +nextSelName, {
+        //     detail: {
+        //       upperVal: item.value
+        //     }
+        //   });
+        //   window.dispatchEvent(event);
+        // }
+
+        // 只在手动选择时自动展开下一级
+        // if (!isAutoEcho.value) {
+        //   const nextLevel = props.level + 1;
+        //   setTimeout(() => {
+        //     const openNextEvent = new CustomEvent('open-next-cascader', {
+        //       detail: {
+        //         name: props.name,
+        //         level: nextLevel
+        //       }
+        //     });
+        //     window.dispatchEvent(openNextEvent);
+        //   }, 100);
+        // }
+      };
+
+      // 监听下一级展开事件 (仅 mode 2)
+      window.addEventListener("cascade-open", (event) => {
+        if (props.mode === "2") {
+          const { level } = event.detail;
+          if (level === props.level) {
+            popupWinVisible.value = true;
+          }
+        }
+      });
+
+      if (props.mode === "1") {
+        //如果是有隐藏字段的下拉菜单
+        // 监听回显事件
+        window.addEventListener(
+            "cascader-echo-" + props.name,
+            async (event) => {
+              const { name, value, isAuto, upperVal } = event.detail;
+              // level,
+              if (upperVal) {
+                upperValue.value = upperVal;
+                console.log(
+                    "value:" +
+                    value +
+                    ",upperValue:" +
+                    upperValue +
+                    ",初始化级联组件时props.name:" +
+                    props.name
+                );
+              }
+
+              // if (name === props.name && level === props.level) {
+              // 设置自动回显标记
+              isAutoEcho.value = true;
+
+              // if (props.opt.length === 0) {
+              // const loadDataEvent = new CustomEvent('cascader-load-data', {
+              //   detail: {
+              //     name: props.name,
+              //     level: props.level,
+              //     value: value
+              //   }
+              // });
+              // window.dispatchEvent(loadDataEvent);
+
+              //下面的代码只用于页面刚打开时,初始化级联菜单的回显值。
+
+              //Vue.watch用于监听数据的变化,并在数据变化时执行特定的回调函数。
+              //这段代码使用了 Vue.js 的 watch API 来监听 props.opt 的变化,如果props.opt有变化,则自动
+
+              //   const unwatch = Vue.watch(
+              //       () => props.opt,                // 监听的数据源(props.opt)
+              //       (newOptions) => {              // 回调函数
+              //         if (newOptions.length > 0) { // 条件判断
+              //           matchAndSelect(value);     // 执行逻辑
+              //           unwatch();                 // 停止监听
+              //         }
+              //       },
+              //       { immediate: true }            // 配置:立即触发一次
+              //   );
+              // } else {
+              //   matchAndSelect(value);
+              // }
+
+              // 初始化级联菜单在页面刚打开时的默认值
+              async function initDefaultValue(value) {
+                try {
+                  // alert(1);
+                  if (props.url && props.param && props.modelValue) {
+                    // alert(2);
+                    /**
+                     *         let objectPickerParam=
+                     *             {"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"hksheng,hkshi,hkxian\"," +
+                     *                     "\"name\":\"hksheng\"," +
+                     *                     "\"cascadingName\":\"dq\",\"cascadingInputsName\":\"hkdqm\"," +
+                     *                     "\"codebook\":\"sheng\"}",
+                     *                 "objectpickertype":2,
+                     *                 "objectpickervalue":"440000"
+                     *             };
+                     */
+
+                    const objectPickerParam = {
+                      input: "false",
+                      cascadingLevel: props.param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
+                      name: props.name, //本下拉菜单名
+                      cascadingName: props.param.name, //级联菜单名
+                      cascadingInputsName: props.param.combField, //对象属性,即隐藏字段名,如:hkdqm
+                      codebook: props.param.codebook,
+                    };
+
+                    const objectPickerParamStr =
+                        JSON.stringify(objectPickerParam);
+
+                    const params = new URLSearchParams();
+                    params.append("objectpickerparam", objectPickerParamStr);
+                    params.append("objectpickertype", "2");
+                    params.append("objectpickervalue", value); //需回显的值
+
+                    axios
+                        .post(props.url, params, {
+                          headers: {
+                            "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                          },
+                        })
+                        .then((response) => {
+                          // alert(JSON.stringify(response.data));
+
+                          if ("timeout" == response.data.statusText) {
+                            alert("网络超时!");
+                            return;
+                          }
+
+                          if (response.data.result) {
+                            const keys = Object.keys(response.data.result);
+                            if (keys.length === 1) {
+                              let code = keys[0];
+                              let desc = response.data.result[keys[0]];
+                              clearAndInit1stOpt();
+                              props.opt.push({ label: desc, value: code });
+
+                              if (value) matchAndSelect(value);
+                              // updateSelectItem();
+
+                              // alert('props.opt:'+JSON.stringify(props.opt));
+                            }
+                          }
+                        });
+                  }
+                } catch (error) {
+                  alert(error);
+                  // callback(null, error.message); // 失败回调,传递错误
+                }
+              }
+
+              //下面的代码只用于页面刚打开时,初始化级联菜单的回显值。
+              initDefaultValue(value);
+
+              // 延迟重置自动回显标记
+              setTimeout(() => {
+                isAutoEcho.value = false;
+              }, 500);
+            }
+        );
+
+        // 被上级下拉菜单触发的,清除选中值和下拉菜单选项
+        window.addEventListener(
+            "cascader-cleanOpt-" + props.name,
+            async (event) => {
+              upperValue.value = "";
+
+              selectItem.value = ""; //清除本下拉菜单当前选中的值
+              emit("update:modelValue", ""); //通知父级
+
+              //清空所有下拉菜单项
+              if (props.opt) {
+                props.opt.length = 0;
+              } else {
+                props.opt = [];
+              }
+
+              //下个下拉菜单名
+              let nextSelName = getNextSel(props.name, props.param.fieldOrd);
+              // alert('nextSelName:'+nextSelName+'--,props.name:'+props.name);
+              if (nextSelName) {
+                //清下个下拉菜单选中值和选项
+                event = new CustomEvent("cascader-cleanOpt-" + nextSelName, {
+                  detail: {},
+                });
+                window.dispatchEvent(event);
+              }
+            }
+        );
+      } else if (props.mode === "2") {
+        //没隐藏字段的下拉菜单,在这初始化默认值
+
+        let needInitParam = undefined;
+        if (Array.isArray(props.param)) {
+          needInitParam = props.param[props.param.length - 1]; //只初始化数组最后一项
+          console.log("needInitParam最后一项:" + JSON.stringify(needInitParam));
+        } else {
+          needInitParam = props.param;
+        }
+
+        // 初始化级联菜单在页面刚打开时的默认值
+        async function initDefaultValue(value, param) {
+          try {
+            // alert(1);
+            if (props.url && param && props.modelValue) {
+              // alert(2);
+              /**
+               *        let param=
+               *             {"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"rylbm,gwid\"," +
+               *                     "\"name\":\"gwid\",\"cascadingName\":\"rylb_gw\"," +
+               *                     "\"codebook\":\"gwByRylb\"}",
+               *                 "objectpickertype":2,
+               *                 "objectpickervalue":"102121"};
+               */
+
+                  // alert('props.name:'+props.name+',props.param.fieldOrd:'+props.param.fieldOrd);
+
+              const objectPickerParam = {
+                    input: "false",
+                    cascadingLevel: param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
+                    name: props.name, //本下拉菜单名
+                    cascadingName: param.name, //级联菜单名
+                    codebook: param.codebook,
+                  };
+
+              const objectPickerParamStr = JSON.stringify(objectPickerParam);
+
+              const sendParams = new URLSearchParams();
+              sendParams.append("objectpickerparam", objectPickerParamStr);
+              sendParams.append("objectpickertype", "2");
+              sendParams.append("objectpickervalue", value); //需回显的值
+
+              axios
+                  .post(props.url, sendParams, {
+                    headers: {
+                      "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                    },
+                  })
+                  .then((response) => {
+                    // alert(JSON.stringify(response.data));
+
+                    if ("timeout" == response.data.statusText) {
+                      alert("网络超时!");
+                      return;
+                    }
+
+                    if (response.data.result) {
+                      const keys = Object.keys(response.data.result);
+
+                      console.log(
+                          "name:" +
+                          props.name +
+                          ",@@级联初始化默认值value:" +
+                          value +
+                          "--param:" +
+                          JSON.stringify(param) +
+                          "--objectPickerParamStr:" +
+                          objectPickerParamStr +
+                          "--response.data:" +
+                          JSON.stringify(response.data)
+                      );
+
+                      if (keys.length === 1) {
+                        let code = keys[0];
+                        let desc = response.data.result[keys[0]];
+
+                        if (props.opt)
+                          props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
+                        else {
+                          props.opt = [];
+                        }
+                        props.opt.push({ label: desc, value: code });
+
+                        if (value) matchAndSelect(value);
+
+                        console.log(
+                            "GOOD mode2回显的默认值:" +
+                            JSON.stringify({ label: desc, value: code }) +
+                            "--props.param:" +
+                            JSON.stringify(param)
+                        );
+
+                        // updateSelectItem();
+
+                        // alert('props.opt:'+JSON.stringify(props.opt));
+                      }
+                    }
+                  });
+            }
+          } catch (error) {
+            alert(error);
+            // callback(null, error.message); // 失败回调,传递错误
+          }
+
+          // 重置自动回显标记
+          isAutoEcho.value = false;
+        }
+
+        // 初始化级联菜单在页面刚打开时的默认值
+        initDefaultValue(props.modelValue, needInitParam);
+
+        //设置mode2的下级下拉菜单的上级菜单当前值
+        setNextSelectUpperValue();
+      }
+
+      //选中要回显的默认值
+      const matchAndSelect = (value) => {
+        const matchedOption = props.opt.find((opt) => opt.value === value);
+        if (matchedOption) {
+          selectItem.value = matchedOption;
+          emit("update:modelValue", value);
+          emit("change", value);
+        }
+      };
+
+      const calculatePopupDirection = () => {
+        // 1. 获取select容器元素
+        const selectEl = document.querySelector(
+            `[name="${props.name}"]`
+        )?.nextElementSibling;
+        console.log("selectEl:" + selectEl, props.name);
+        if (!selectEl) return;
+
+        // 2. 获取位置信息
+        const selectRect = selectEl.getBoundingClientRect();
+        const viewportHeight = window.innerHeight;
+
+        // 3. 简单判断:如果下方剩余空间小于300px就向上弹出
+        const spaceBelow = viewportHeight - selectRect.bottom;
+
+        // 调试信息
+        console.log("空间判断:", {
+          elementBottom: selectRect.bottom,
+          viewportHeight,
+          spaceBelow,
+          willPopUp: spaceBelow < 300,
+          popupDirection: popupDirection.value,
+        });
+
+        // 4. 设置方向
+        popupDirection.value = spaceBelow < 300 ? "top" : "bottom";
+      };
+      //级联菜单点击事件
+      const togglePopup = () => {
+        if (!popupWinVisible.value) {
+          //如果当前下拉菜单是隐藏的,先ajax重新加载下拉菜单项,再显示。
+
+          showPopup();
+        } else {
+          hidePopup();
+        }
+      };
+
+      //显示下拉菜单,在此之前先清除下拉菜单项
+      const showPopup = () => {
+        //清空下拉菜单,并设置第一项的值为空
+        clearAndInit1stOpt();
+        Vue.nextTick(() => {
+          calculatePopupDirection();
+        });
+        let url = props.url;
+        let filterObj = props.param.filter;
+
+        if (filterObj) {
+          for (let k in filterObj) {
+            let v = filterObj[k];
+            url += "&" + k + "=" + v;
+          }
+        }
+
+        if (props.mode === "1") {
+          //如果是有隐藏字段的下拉菜单
+
+          console.log("666url:" + url);
+
+          // alert('url:'+url);
+
+          // 获取级联菜单所有下拉菜单项
+          async function getSelectItems(value) {
+            try {
+              // alert(1);
+              if (props.url && props.param) {
+                // alert(2);
+                /**
+                 *            param={"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"hksheng,hkshi,hkxian\"," +
+                 *                     "\"name\":\"hksheng\",\"cascadingName\":\"dq\"," +
+                 *                     "\"cascadingInputsName\":\"hkdqm\",\"codebook\":\"sheng\"}",
+                 *                 "objectpickertype":1,//2表示获取要回显的一项,1表示获取所有下拉菜单项
+                 *                 "upperValue":"440000"
+                 *             };
+                 */
+
+                const objectPickerParam = {
+                  input: "false",
+                  cascadingLevel: props.param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
+                  name: props.name, //本下拉菜单名
+                  cascadingName: props.param.name, //级联菜单名
+                  cascadingInputsName: props.param.combField, //对象属性,即隐藏字段名,如:hkdqm
+                  codebook: props.param.codebook,
+                };
+
+                console.log("mode1 upperValue.value:" + upperValue.value);
+
+                const objectPickerParamStr = JSON.stringify(objectPickerParam);
+
+                const params = new URLSearchParams();
+                params.append("objectpickerparam", objectPickerParamStr);
+                params.append("objectpickertype", "1");
+                if (upperValue.value) {
+                  params.append("upperValue", upperValue.value);
+                }
+                // params.append('objectpickervalue', value); //需回显的值
+
+                axios
+                    .post(url, params, {
+                      headers: {
+                        "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                      },
+                    })
+                    .then((response) => {
+                      if ("timeout" == response.data.statusText) {
+                        alert("网络超时!");
+                        return;
+                      }
+
+                      if (response.data.result) {
+                        const keys = Object.keys(response.data.result);
+                        console.log(
+                            "params:" +
+                            params +
+                            "@@response.data:" +
+                            JSON.stringify(response.data)
+                        );
+
+                        if (keys.length > 0) {
+                          for (let k in response.data.result) {
+                            props.opt.push({
+                              label: response.data.result[k],
+                              value: k,
+                            });
+                          }
+
+                          if (!popupWinVisible.value) {
+                            popupWinVisible.value = true; // 确保下拉框打开
+                          }
+
+                          console.log("props.opt11:" + JSON.stringify(props.opt));
+                        }
+                      }
+                    });
+              }
+            } catch (error) {
+              alert(error);
+              // callback(null, error.message); // 失败回调,传递错误
+            }
+          }
+
+          getSelectItems(props.modelValue);
+        } else if (props.mode === "2") {
+          //没隐藏字段的下拉菜单
+
+          let needInitParam = undefined;
+          if (Array.isArray(props.param)) {
+            needInitParam = props.param[props.param.length - 1]; //只初始化数组最后一项
+            console.log(
+                "needInitParam最后一项:" + JSON.stringify(needInitParam)
+            );
+          } else {
+            needInitParam = props.param;
+          }
+
+          // 获取级联菜单所有下拉菜单项
+          async function getSelectItems(value, sendParam) {
+            try {
+              // alert(1);
+              if (props.url && sendParam) {
+                // alert(2);
+                /**
+                 *            param="{\"input\":\"false\",\"cascadingLevel\":\"dwid,sjryid\",
+                 *            \"ryid\":\"111121\",\"name\":\"sjryid\",
+                 *            \"cascadingName\":\"dw_sjry\",\"codebook\":\"sjryByDw\"}"
+                 */
+
+                const objectPickerParam = {
+                  input: "false",
+                  cascadingLevel: sendParam.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
+                  name: props.name, //本下拉菜单名
+                  cascadingName: sendParam.name, //级联菜单名
+                  codebook: sendParam.codebook,
+                };
+
+                console.log("mode2 upperValue.value:" + upperValue.value);
+
+                const objectPickerParamStr = JSON.stringify(objectPickerParam);
+
+                const params = new URLSearchParams();
+                params.append("objectpickerparam", objectPickerParamStr);
+                params.append("objectpickertype", "1");
+                if (upperValue.value) {
+                  params.append("upperValue", upperValue.value);
+                }
+                // params.append('objectpickervalue', value); //需回显的值
+
+                axios
+                    .post(url, params, {
+                      headers: {
+                        "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                      },
+                    })
+                    .then((response) => {
+                      if ("timeout" == response.data.statusText) {
+                        alert("网络超时!");
+                        return;
+                      }
+
+                      if (response.data.result) {
+                        const keys = Object.keys(response.data.result);
+                        console.log(
+                            "params:" +
+                            params +
+                            "@@response.data:" +
+                            JSON.stringify(response.data)
+                        );
+
+                        if (keys.length > 0) {
+                          for (let k in response.data.result) {
+                            props.opt.push({
+                              label: response.data.result[k],
+                              value: k,
+                            });
+                          }
+
+                          if (!popupWinVisible.value) {
+                            popupWinVisible.value = true; // 确保下拉框打开
+                          }
+
+                          console.log("props.opt11:" + JSON.stringify(props.opt));
+                        }
+                      }
+                    });
+              }
+            } catch (error) {
+              alert(error);
+              // callback(null, error.message); // 失败回调,传递错误
+            }
+          }
+
+          getSelectItems(props.modelValue, needInitParam);
+
+          // popupWinVisible.value = !popupWinVisible.value;
+        }
+      };
+
+      const hidePopup = () => {
+        popupWinVisible.value = false;
+      };
+
+      // 合并所有的 onMounted 逻辑
+      Vue.onMounted(() => {
+        window.addEventListener("resize", calculatePopupDirection);
+
+        // 1. 监听展开下一级事件
+        window.addEventListener("open-next-cascader", (event) => {
+          const { name, level } = event.detail;
+          if (name === props.name && level === props.level) {
+            popupWinVisible.value = true;
+          }
+        });
+
+        // 2. 监听级联事件
+        window.addEventListener("cascader-change", (event) => {
+          const { name, level, value } = event.detail;
+          if (name === props.name && level < props.level) {
+            selectItem.value = { label: "", value: "" };
+            emit("update:modelValue", "");
+            if (ssHidden) {
+              ssHidden.updateValue(value);
+            }
+          }
+        });
+      });
+      Vue.onUnmounted(() => {
+        window.removeEventListener("resize", calculatePopupDirection);
+      });
+      // 监听值变化,处理回显 (mode 2)
+      Vue.watch(
+          () => props.modelValue,
+          (newVal) => {
+            if (props.mode === "2" && newVal) {
+              // 使用 watchEffect 替代嵌套的 watch
+              Vue.watchEffect(() => {
+                if (props.opt.length > 0) {
+                  const matchedOption = props.opt.find(
+                      (opt) => opt.value === newVal
+                  );
+                  if (matchedOption) {
+                    selectItem.value = matchedOption;
+                  }
+                }
+              });
+            } else {
+              // 原有的值变化处理
+              const item = props.opt.find((it) => it.value === newVal);
+              if (item) {
+                selectItem.value = item;
+              } else {
+                selectItem.value = { label: "", value: "" };
+              }
+            }
+          },
+          { immediate: true }
+      );
+
+      // 监听选项变化,当数据加载完成时进行匹配
+      Vue.watch(
+          () => props.opt,
+          (newOptions) => {
+            if (newOptions.length > 0) {
+              const matchedOption = newOptions.find(
+                  (opt) => opt.value === selectItem.value.value
+              );
+              if (matchedOption) {
+                selectItem.value = matchedOption;
+                emit("update:modelValue", matchedOption.value);
+                emit("change", matchedOption.value);
+              }
+            }
+          }
+      );
+
+      return {
+        selectItem,
+        popupWinVisible,
+        popupDirection,
+        togglePopup,
+        hidePopup,
+        doSelectItem,
+      };
+    },
+
+    template: `
+      <div class="input" style="position: relative" :style="{width: width}">
+        <input type="hidden" :name="name" :value="modelValue">
+        <div class="select-container" @mouseleave="hidePopup">
+          <div class="input" @click="togglePopup">
+            <input 
+              type="hidden"
+              :name="name"
+              :value="selectItem.value"
+            />
+            <input
+              :placeholder="placeholder"
+              :value="selectItem.label"
+              disabled
+              style="pointer-events: none;"
+            />
+            <div class="suffix">
+              <ss-form-icon :class="popupWinVisible ? 'form-icon-transform-select select' : 'form-icon-select'" />
+            </div>
+          </div>
+
+          <div v-show="popupWinVisible" class="popup-win " :class="popupDirection">
+            <div v-if="opt && opt.length > 0" class="popup-content">
+              <div class="content-area">
+                <div 
+                  v-for="(item, index) in opt" 
+                  :key="index" 
+                  @click="doSelectItem(item)" 
+                  :class="{ active: item.value === selectItem.value }"
+                >
+                  <span class="check-icon">
+                    <ss-form-icon class="form-icon-select-checked" />
+                  </span>
+                  <span>{{ item.label }}</span>
+                </div>
+              </div>
+            </div>
+            <div v-else class="popup-content">
+              <div class="content-area">
+                <div class="content-area">
+                  <span>无选项</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `,
+  };
+  // ss-date-picker 日期时间选择器组件
+  const SsDatePicker = {
+    name: "SsDatePicker",
+    props: {
+      modelValue: {
+        type: [String, Number, Date],
+        default: "",
+      },
+      name: {
+        type: String,
+        required: true,
+      },
+      type: {
+        type: String,
+        default: "date",
+        validator: (value) => ["date", "datetime", "time"].includes(value),
+      },
+      fmt: {
+        type: String,
+        default: null,
+      },
+      placeholder: {
+        type: String,
+        default: "",
+      },
+      width: {
+        type: String,
+        default: "100%",
+      },
+    },
+
+    emits: ["update:modelValue"],
+
+    setup(props, { emit }) {
+      const errMsg = ref("");
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          console.log("validate", window.ssVm.validateField(props.name));
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+      // 根据type确定默认格式
+      const defaultFormat = computed(() => {
+        switch (props.type) {
+          case "datetime":
+            return "YYYY-MM-DD HH:mm:ss";
+          case "date":
+            return "YYYY-MM-DD";
+          case "time":
+            return "HH:mm:ss";
+        }
+      });
+      const convertJavaFormatToElement = (javaFormat) => {
+        if (!javaFormat) return null;
+        return javaFormat
+            .replace("yyyy", "YYYY")
+            .replace("MM", "MM")
+            .replace("dd", "DD")
+            .replace("HH", "HH")
+            .replace("mm", "mm")
+            .replace("ss", "ss");
+      };
+
+      const finalFormat = computed(() => {
+        if (props.fmt) {
+          return convertJavaFormatToElement(props.fmt);
+        }
+        return defaultFormat.value;
+      });
+
+      // 使用 resolveComponent 获取组件
+      const ElDatePicker = resolveComponent("ElDatePicker");
+      const ElTimePicker = resolveComponent("ElTimePicker");
+      const SsFormIcon = resolveComponent("SsFormIcon");
+      const ElIcon = resolveComponent("ElIcon");
+
+      const handleValueUpdate = (val) => {
+        emit("update:modelValue", val);
+        emit("change", val); // 同时触发 change 事件
+        setTimeout(() => {
+          validate();
+        }, 50);
+      };
+      const dateType = computed(() => {
+        const fmt = props.fmt || "";
+        if (fmt.includes("HH:mm:ss")) {
+          return "datetime";
+        } else if (fmt.includes("HH:mm")) {
+          return "datetime";
+        } else if (fmt.includes("mm:ss")) {
+          return "time";
+        }
+        return "date";
+      });
+
+      let useTimePicker = true;
+      //"yyyy-MM-dd HH:mm:ss";  "日期字符串格式在java的写法",传到本组件fmt属性也是按这个格式
+      if (props.fmt) {
+        //有fmt属性,则以fmt属性优先判断类型
+        if (/[dMy]/.test(props.fmt)) {
+          //如果有传入日期格式,且含年月日
+          useTimePicker = false;
+        } else {
+          useTimePicker = true;
+        }
+      } else if (props.type !== "time") {
+        useTimePicker = false;
+      }
+
+      return () =>
+          h("div", { class: "ss-date-picker", style: { width: props.width } }, [
+            h("input", {
+              type: "hidden",
+              name: props.name,
+              value: props.modelValue,
+            }),
+            // 选择组件
+            h(useTimePicker ? ElTimePicker : ElDatePicker, {
+              modelValue: props.modelValue,
+              "onUpdate:modelValue": handleValueUpdate,
+              type: dateType.value,
+              format: finalFormat.value,
+              "value-format": finalFormat.value,
+              clearable: true,
+              placeholder: props.placeholder,
+              class: "custom-date-picker", // 用于自定义样式
+              "time-arrow-control": props.type === "datetime", // 修改这里
+              size: "large", // 添加这一行,改为 large 尺寸
+              style: { width: "100%" },
+              "prefix-icon": h(SsFormIcon, { class: "form-icon-time" }),
+            }),
+          ]);
+    },
+  };
+  // ss-icon 图标
+  const SsIcon = {
+    name: "SsIcon",
+    props: {
+      name: { type: String, required: true },
+      size: { type: [Number, String], default: 16 },
+      unit: { type: String, default: "px" },
+      color: String,
+      type: {
+        type: String,
+        default: ssIcon.name,
+        validator: function (value) {
+          return [ssIcon, commonIcon].some((icon) => icon.name === value);
+        },
+      },
+    },
+    emits: ["update:modelValue", "input", "blur", "change"],
+    setup(props, { emit }) {
+      const useIconType = computed(() => {
+        return [ssIcon, commonIcon].find(
+            (iconConfig) => iconConfig.name === props.type
+        );
+      });
+      const iconName = computed(() => {
+        const iconConfig = useIconType.value; // 注意:使用 .value 来访问响应式引用的值
+        if (!iconConfig) {
+          console.error(`Icon type "${props.type}" not found.`);
+          return "";
+        }
+        const iconType = iconConfig.types[props.name];
+        if (!iconType) {
+          console.error(
+              `Icon name "${props.name}" not found in type "${props.type}".`
+          );
+          return "";
+        }
+        return `${iconConfig.prefix}${iconType}`;
+      });
+
+      // 类似地,你可以计算 fontFamily 和 style
+      const fontFamily = computed(() => {
+        return useIconType.value ? useIconType.value.family : "";
+      });
+      // console.log(iconName.value,fontFamily.value)
+      const style = computed(() => {
+        const sizeStyle = isNum(props.size)
+            ? `${props.size}${props.unit}`
+            : props.size;
+        const styleObj = {
+          fontSize: sizeStyle,
+          color: props.color || "",
+        };
+        return toStyleStr(styleObj);
+      });
+
+      // 使用渲染函数定义模板逻辑
+      return () =>
+          h("i", {
+            class: ["icon-container", iconName.value, fontFamily.value],
+            style: style.value,
+          });
+    },
+  };
+  // 通用icon
+  const SsCommonIcon = {
+    name: "SsCommonIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("i", {
+            class: props.class + " common-icon",
+          });
+    },
+  };
+  // 登录页icon
+  const SsLoginIcon = {
+    name: "SsLoginIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " login-icon",
+          });
+    },
+  };
+  // 弹窗icon
+  const SsDialogIcon = {
+    name: "SsDialogIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("i", {
+            class: props.class + " dialog-icon",
+          });
+    },
+  };
+  // 全局左侧导航图标组件
+  const SsNavIcon = {
+    name: "SsNavIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " nav-icon",
+          });
+    },
+  };
+  // 顶部工具栏图标组件
+  const SsHeaderIcon = {
+    name: "SsHeaderIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " header-icon",
+          });
+    },
+  };
+  // 全局菜单图标组件
+  const SsGolbalMenuIcon = {
+    name: "SsGolbalMenuIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " global-menu-icon",
+          });
+    },
+  };
+  // 全局查询列表卡片图标
+  const SsCartListIcon = {
+    name: "SsCartListIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " cart-list-icon",
+          });
+    },
+  };
+  // 全局底部工具栏图标组件
+  const SsQuickIcon = {
+    name: "SsQuickIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " quick-icon",
+          });
+    },
+  };
+  // 表单组件icon
+  const SsFormIcon = {
+    name: "SsFormIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " form-icon",
+          });
+    },
+  };
+  // 弹窗底部按钮icon
+  const SsBottomDivIcon = {
+    name: "SsBottomDivIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("div", {
+            class: props.class + " bottom-div-icon",
+          });
+    },
+  };
+  // editor组件icon
+  const SsEditorIcon = {
+    name: "SsEditorIcon",
+    props: {
+      class: {
+        type: String,
+        required: true,
+      },
+    },
+    setup(props) {
+      return () =>
+          h("i", {
+            class: props.class + " editor-icon",
+          });
+    },
+  };
+  // ss-validate校验器
+  const SsValidate = {
+    name: "SsValidate",
+    props: {
+      errMsg: { type: String },
+      textAlign: { type: String, default: "left" },
+      style: { type: Object, default: () => ({}) },
+    },
+    template: `<div class="validate-vline"></div>
+    <div class="validate-tip" :style="style">
+      <div class="tip" :style="{ textAlign: textAlign }">{{ errMsg }}</div>
+      <div class="tip-more" :style="{ textAlign: textAlign }">{{ errMsg }}</div>
+    </div>`,
+  };
+  // ss-onoffbutton-array 多选按钮 数组形式
+  const SsOnoffbuttonArray = {
+    name: "SsOnoffbuttonArray",
+    props: {
+      name: {
+        type: String,
+        required: true,
+      },
+      opt: {
+        type: Array,
+        default: () => [],
+      },
+      defaultValue: [String, Number, Array],
+      modelValue: [String, Number, Array],
+      multiple: {
+        // 新增多选模式属性
+        type: Boolean,
+        default: false,
+      },
+    },
+    emits: ["update:modelValue"], // 允许更新 v-model 绑定的值
+    setup(props, { emit }) {
+      console.log("多选按钮", props.opt);
+      // 使用数组来存储选中值
+      const checkedValue = ref(
+          props.multiple
+              ? Array.isArray(props.defaultValue)
+                  ? props.defaultValue
+                  : []
+              : props.defaultValue
+      );
+      const errMsg = ref(props.errTip);
+
+      // 生成icon名字
+      const genIconName = (itemValue) => {
+        if (props.multiple) {
+          return checkedValue.value.includes(itemValue)
+              ? "form-icon-onoffbutton-checked"
+              : "form-icon-onoffbutton-unchecked";
+        }
+        return checkedValue.value === itemValue
+            ? "form-icon-onoffbutton-checked"
+            : "form-icon-onoffbutton-unchecked";
+      };
+      // 选中项
+      const selectItem = (value) => {
+        if (props.multiple) {
+          // 多选模式
+          const index = checkedValue.value.indexOf(value);
+          if (index === -1) {
+            checkedValue.value = [...checkedValue.value, value];
+          } else {
+            checkedValue.value = checkedValue.value.filter((v) => v !== value);
+          }
+        } else {
+          // 单选模式
+          checkedValue.value = value;
+        }
+
+        emit("update:modelValue", checkedValue.value);
+        nextTick(() => {
+          // 触发验证
+          if (window.ssVm) {
+            window.ssVm.validateField(props.name);
+          }
+        });
+      };
+
+      return { checkedValue, genIconName, selectItem };
+    },
+    // 使用渲染函数定义模板逻辑
+    render() {
+      const SsFormIcon = resolveComponent("ss-form-icon");
+      return h("div", { class: "radio-container" }, [
+        // 根据情况创建 input
+        this.multiple
+            ? this.checkedValue.length
+                ? // 多选且有选中值:为选中项创建 input
+                this.checkedValue.map((value) =>
+                    h("input", {
+                      type: "checkbox",
+                      name: this.name,
+                      value: value,
+                      checked: true,
+                      style: { display: "none" },
+                    })
+                )
+                : // 多选但没有选中值:创建一个空值 input
+                h("input", {
+                  type: "hidden",
+                  name: this.name,
+                  value: "",
+                })
+            : // 单选模式:创建一个 input
+            h("input", {
+              type: "hidden",
+              name: this.name,
+              value: this.checkedValue || "",
+            }),
+
+        this.opt.map((item, i) =>
+            h(
+                "div",
+                {
+                  key: i,
+                  class: {
+                    checked: this.multiple
+                        ? this.checkedValue.includes(item.value)
+                        : this.checkedValue === item.value,
+                  },
+                  style: { width: item.width },
+                  onClick: () => this.selectItem(item.value),
+                },
+                [
+                  h("span", null, item.label),
+                  h("div", { class: "mark" }, [
+                    h(SsFormIcon, {
+                      class: this.genIconName(item.value),
+                    }),
+                  ]),
+                ]
+            )
+        ),
+      ]);
+    },
+  };
+
+  // ss-onoffbutton 一个按钮
+  const SsOnoffbutton = {
+    name: "SsOnoffbutton",
+    props: {
+      name: {
+        type: String,
+        required: true,
+      },
+      label: {
+        type: String,
+        required: true,
+      },
+      value: {
+        type: [String, Number],
+        required: true,
+      },
+      width: {
+        type: String,
+        default: "",
+      },
+      modelValue: [String, Number, Array],
+      multiple: {
+        type: Boolean,
+        default: false,
+      },
+    },
+    emits: ["update:modelValue"],
+
+    setup(props, { emit }) {
+      const parseModelValue = (val) => {
+        if (!val) return [];
+        // 如果以逗号开头,去掉开头的逗号
+        const cleanValue = val.toString().replace(/^,+/, "");
+        if (cleanValue.includes("|")) {
+          return cleanValue.split("|");
+        }
+        if (cleanValue.includes(",")) {
+          return cleanValue.split(",");
+        }
+        return [cleanValue];
+      };
+      // 判断当前按钮是否选中
+      const isChecked = computed(() => {
+        if (props.multiple) {
+          const currentValue = parseModelValue(props.modelValue);
+          return currentValue.includes(props.value.toString());
+
+          // return Array.isArray(props.modelValue) && props.modelValue.includes(props.value);
+        }
+        return props.modelValue === props.value;
+      });
+
+      // 切换选中状态
+      const toggleSelect = () => {
+        if (props.multiple) {
+          const currentValue = parseModelValue(props.modelValue);
+          const index = currentValue.indexOf(props.value.toString());
+          let newValue;
+          if (index === -1) {
+            newValue = [...currentValue, props.value];
+          } else {
+            newValue = currentValue.filter((v) => v !== props.value.toString());
+          }
+          emit("update:modelValue", newValue.join(","));
+        } else {
+          emit("update:modelValue", props.value);
+        }
+
+        nextTick(() => {
+          // 触发验证
+          if (window.ssVm) {
+            window.ssVm.validateField(props.name);
+          }
+        });
+      };
+
+      return { isChecked, toggleSelect };
+    },
+
+    render() {
+      const SsFormIcon = resolveComponent("ss-form-icon");
+      return h("div", { class: "radio-container2" }, [
+        // 隐藏的表单元素
+        this.multiple
+            ? h("input", {
+              type: "hidden",
+              name: `${this.name}`, // 多选模式下使用数组形式的 name
+              value: this.isChecked ? this.value : "",
+            })
+            : this.isChecked &&
+            h("input", {
+              // 只有当前按钮被选中时才创建 input
+              type: "hidden",
+              name: this.name,
+              value: this.value,
+            }),
+
+        // 按钮显示
+        h(
+            "div",
+            {
+              class: { checked: this.isChecked },
+              style: { width: this.width },
+              onClick: this.toggleSelect,
+            },
+            [
+              h("span", null, this.label),
+              h("div", { class: "mark" }, [
+                h(SsFormIcon, {
+                  class: this.isChecked
+                      ? "form-icon-onoffbutton-checked"
+                      : "form-icon-onoffbutton-unchecked",
+                }),
+              ]),
+            ]
+        ),
+      ]);
+    },
+  };
+
+  // ss-textarea
+  const SsTextarea = {
+    name: "SsTextarea",
+    props: {
+      name: {
+        type: String,
+        required: true,
+      },
+      placeholder: {
+        type: String,
+        default: "请输入",
+      },
+      defaultValue: [String, Number],
+      modelValue: [String, Number],
+    },
+    emits: ["update:modelValue"],
+    setup(props, { emit }) {
+      const inputValue = ref(props.modelValue || props.defaultValue || "");
+
+      // 监听 modelValue 变化
+      watch(
+          () => props.modelValue,
+          (newVal) => {
+            inputValue.value = newVal;
+          }
+      );
+
+      // 输入事件处理
+      const onInput = (event) => {
+        const newValue = event.target.value;
+        inputValue.value = newValue;
+        emit("update:modelValue", newValue);
+        // 触发验证
+        if (window.ssVm) {
+          window.ssVm.validateField(props.name);
+        }
+      };
+
+      // 失焦时验证
+      const onBlur = () => {
+        if (window.ssVm) {
+          window.ssVm.validateField(props.name);
+        }
+      };
+
+      return { inputValue, onInput, onBlur };
+    },
+    render() {
+      return h("div", { class: "textarea-container" }, [
+        h("div", { class: "textarea" }, [
+          // 添加隐藏的 input 用于验证
+          h("input", {
+            type: "hidden",
+            name: this.name,
+            value: this.inputValue || "",
+          }),
+          h("textarea", {
+            placeholder: this.placeholder,
+            value: this.inputValue,
+            onInput: this.onInput,
+            onBlur: this.onBlur,
+          }),
+        ]),
+      ]);
+    },
+  };
+  // ss-editor 富文本编辑器 基于Jodit
+  const SsEditor = {
+    name: "SsEditor",
+    props: {
+      modelValue: {
+        type: String,
+        default: "",
+      },
+      name: {
+        type: String,
+        default: "",
+      },
+      url: {
+        type: String,
+        default: "",
+      },
+      height: {
+        type: [Number, String],
+        default: 400,
+      },
+      placeholder: {
+        type: String,
+        default: "请输入内容",
+      },
+      readonly: {
+        type: Boolean,
+        default: false,
+      },
+      uploadUrl: {
+        type: String,
+        default: "/upload",
+      },
+      param: {
+        type: Object,
+        default: () => ({}),
+      },
+    },
+
+    emits: ["update:modelValue", "ready", "change"],
+
+    setup(props, { emit }) {
+      const SsEditorIcon = resolveComponent("SsEditorIcon");
+      const editorRef = ref(null);
+      let editorContent = '';//保存富文本编辑器里面的富文本内容
+      const uniqueId = "editor-" + Date.now();
+      const errMsg = Vue.ref("");
+      let fjid = ref(props.param.button.val);
+      let fjName = props.param.button.desc;
+      let mode = props.param.mode;
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          console.log("validate", window.ssVm.validateField(props.name));
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+      onMounted(() => {
+        validate();
+        const editor = Jodit.make(`#${uniqueId}`, {
+          height: props.height,
+          placeholder: props.placeholder,
+          readonly: props.readonly,
+          language: "zh_cn",
+          i18n: {
+            zh_cn: {
+              Link: "链接",
+              URL: "链接",
+              "No follow": "无跟踪",
+              "Class name": "类名",
+              Image: "图片",
+              File: "文件",
+              "Line height": "行高",
+              Alternative: "描述",
+              "Alternative text": "描述",
+              "Lower Alpha": "小写字母",
+              "Upper Alpha": "大写字母",
+              "Upper Roman": "大写罗马数字",
+              "Lower Roman": "小写罗马数字",
+              "Lower Greek": "小写希腊字母",
+              "Lower Letter": "小写字母",
+              "Upper Letter": "大写字母",
+            },
+          },
+          showXPathInStatusbar: false,
+          showCharsCounter: false,
+          showWordsCounter: false,
+          allowResizeY: false,
+          toolbarSticky: false,
+
+          statusbar: false,
+          uploader: {
+            url: props.uploadUrl,
+            format: "json",
+            method: "POST",
+            filesVariableName: function (i) {
+              return "imgs[" + i + "]";
+            },
+            headers: {
+              Accept: "application/json",
+            },
+            prepareData: function (formData) {
+              // 这里可以在发送前处理表单数据
+              return formData;
+            },
+            isSuccess: function (resp) {
+              console.log("isSuccess resp:", resp);
+              return resp.code === 0;
+            },
+            getMessage: function (resp) {
+              console.log("getMessage resp:", resp);
+              return resp.msg || "上传失败";
+            },
+            process: function (resp) {
+              console.log("process resp:", resp);
+              return resp.data.url;
+            },
+            error: function (e) {
+              console.error("上传失败:", e.message);
+            },
+            defaultHandlerSuccess: function (resp) {
+              console.log("上传成功:", resp);
+            },
+            defaultHandlerError: function (err) {
+              console.error("上传错误:", err);
+            },
+            contentType: function (requestData) {
+              // 可以根据需要修改 Content-Type
+              return false; // 让浏览器自动设置
+            },
+          },
+
+          // 自定义字体列表
+          controls: {
+            font: {
+              list: {
+                Arial: "Arial",
+                SimSun: "宋体",
+                SimHei: "黑体",
+                "Microsoft YaHei": "微软雅黑",
+                KaiTi: "楷体",
+                FangSong: "仿宋",
+                "Times New Roman": "Times New Roman",
+                "Courier New": "Courier New",
+              },
+            },
+            customLinkButton: {
+              name: "link",
+              tooltip: "附件",
+              exec: function (editor) {
+                // 按钮点击时的处理函数
+                console.log("附件点击了");
+                console.log("param", props.param);
+                console.log("cmsAddUrl",props.param.button.cmsAddUrl);
+
+                if (fjid.value == null || fjid.value == "") {
+                  $.ajax({
+                    type: "post",
+                    url: props.param.button.cmsAddUrl,
+                    async: false,
+                    data: {
+                      name: "fjid",
+                      ssNrObjName: "sh",
+                      ssNrObjId: "",
+                    },
+                    success: function (_fjid) {
+                      console.log("cmsAddUrl success", _fjid);
+                      fjid.value = _fjid;
+                    },
+                  });
+                }
+                var str =
+                    "&nrid=T-" +
+                    fjid.value +
+                    "&objectId=" +
+                    fjid.value +
+                    "&objectName=" +
+                    fjName +
+                    "&callback=" +
+                    (window["fjidCallbackName"] || "");
+                console.log("str", str);
+                SS.openDialog({
+                  src: props.param.button.cmsUpdUrl + str,
+                  headerTitle: "编辑",
+                  width: 900,
+                  high: 664,
+                  zIndex:51
+                });
+                // ss.display.showComponent({
+                //   show: ["wdDialog"],
+                //   url: props.param.button.cmsUpdUrl + str,
+                //   title: "编辑",
+                //   width: 900,
+                //   high: 664,
+                // });
+              },
+            },
+          },
+          toolbarAdaptive: true,
+          buttons: [
+            "fullsize",
+            "bold",
+            "italic",
+            "underline",
+            "strikethrough",
+            "eraser",
+            "|",
+            "font",
+            "fontsize",
+            "brush",
+            "paragraph",
+            "|",
+            "left",
+            "center",
+            "right",
+            "justify",
+            "|",
+            "ul",
+            "ol",
+            "indent",
+            "outdent",
+            "|",
+            "image",
+            "table",
+            "customLinkButton",
+            "print",
+            "|",
+            "undo",
+            "redo",
+            "find",
+          ],
+          // 中等宽度时显示的按钮
+          buttonsMD: [
+            "fullsize",
+            "bold",
+            "italic",
+            "underline",
+            "strikethrough",
+            "eraser",
+            "|",
+            "font",
+            "fontsize",
+            "brush",
+            "paragraph",
+            "|",
+            "font",
+            "fontsize",
+            "|",
+            "left",
+            "center",
+            "right",
+            "justify",
+            "|",
+            "image",
+            "customLinkButton",
+            "|",
+            "dots", // 其余按钮会自动进入 dots 菜单
+          ],
+
+          // 小屏幕时显示的按钮
+          buttonsSM: ["fullsize", "bold", "italic", "|", "image", "|", "dots"],
+
+          // 超小屏幕时显示的按钮
+          buttonsXS: ["fullsize", "bold", "|", "dots"],
+          // 设置响应式断点
+          sizeLG: 1024, // 大屏幕
+          sizeMD: 768, // 中等屏幕
+          sizeSM: 576, // 小屏幕
+          // 自定义图标
+          getIcon: function (name, clearName) {
+            // 定义图标映射
+            const iconMap = {
+              bold: "editor-icon-bold",
+              italic: "editor-icon-italic",
+              underline: "editor-icon-underline",
+              strikethrough: "editor-icon-strikethrough",
+              eraser: "editor-icon-eraser",
+              copyformat: "editor-icon-copyformat",
+              font: "editor-icon-font",
+              fontsize: "editor-icon-fontsize",
+              brush: "editor-icon-brush",
+              paragraph: "editor-icon-paragraph",
+              left: "editor-icon-align-left",
+              center: "editor-icon-align-center",
+              right: "editor-icon-align-right",
+              justify: "editor-icon-align-justify",
+              ul: "editor-icon-ul",
+              ol: "editor-icon-ol",
+              indent: "editor-icon-indent",
+              outdent: "editor-icon-outdent",
+              image: "editor-icon-image",
+              file: "editor-icon-file",
+              video: "editor-icon-video",
+              table: "editor-icon-table",
+              link: "editor-icon-link",
+              source: "editor-icon-source",
+              eye: "editor-icon-preview",
+              fullsize: "editor-icon-fullsize",
+              shrink: "editor-icon-fullsize-exit", // 添加退出全屏图标
+
+              print: "editor-icon-print",
+              undo: "editor-icon-undo",
+              redo: "editor-icon-redo",
+              search: "editor-icon-find",
+              selectall: "editor-icon-selectall",
+            };
+            // 获取对应的图标类名
+            const iconClass = iconMap[clearName] || iconMap[name];
+
+            if (iconClass) {
+              // 返回带有我们自定义图标类的 span 元素
+              return `<span class="editor-icon ${iconClass}"></span>`;
+            }
+
+            return null;
+          },
+        });
+
+
+
+        // 设置初始值
+        editor.value = editorContent;
+        // editor.value = props.modelValue;
+
+        // 监听变化
+        editor.events.on("change", () => {
+          // emit("update:modelValue", editor.value);
+          editorContent = editor.value;
+          // alert('editorContent:'+editorContent);
+          let contentElements = document.getElementsByName(props.name.replace(/wj$/, "") + "Edit");
+          if(contentElements.length>0){
+            contentElements[0].value = editorContent;
+          }
+          emit("change", editor.value);
+          setTimeout(() => {
+            validate();
+          }, 50);
+        });
+
+        // 保存编辑器实例
+        editorRef.value = editor;
+
+        emit("ready", editor);
+
+        //回显编辑器富文本文件
+        if (props.url ) {
+          const params = new URLSearchParams();
+
+        if(mode)
+          params.append("mode", mode);
+
+          if(props.modelValue)
+            params.append("path", props.modelValue);
+
+          // alert('props.url:'+props.url+',props.modelValue:'+props.modelValue);
+
+          axios
+              .post(props.url, params, {
+                headers: {
+                  "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
+                },
+              })
+              .then((response) => {
+                // alert(JSON.stringify(response.data));
+
+                if ("timeout" == response.data.statusText) {
+                  alert("网络超时!");
+                  return;
+                }
+
+                let content = response.data.content;
+                if (content) {
+                  // editor.value = content;
+                  editorRef.value.value = content;
+                  editorContent = content;
+                  // alert('editor.value:'+editor.value)
+                }
+
+                let filePath = response.data.path;
+                // alert('response.data:'+JSON.stringify(response.data));
+                if(filePath){
+                  props.modelValue = filePath;
+                  emit("update:modelValue", filePath);
+                }
+              });
+        }
+      });
+
+      // 监听值变化
+      watch(
+          // () => props.modelValue,
+          () => editorContent,
+          (newValue) => {
+            if (editorRef.value && newValue !== editorRef.value.value) {
+              editorRef.value.value = newValue || "";
+            }
+          }
+      );
+
+      // 监听只读状态变化
+      watch(
+          () => props.readonly,
+          (newValue) => {
+            if (editorRef.value) {
+              editorRef.value.setReadOnly(newValue);
+            }
+          }
+      );
+
+      // 组件销毁时清理
+      onBeforeUnmount(() => {
+        if (editorRef.value) {
+          editorRef.value.destruct();
+        }
+      });
+
+      return () =>
+          h("div", { class: "ss-editor-container" }, [
+            fjid.value &&
+            h("input", {
+              type: "hidden",
+              name: "fjid",
+              value: fjid.value,
+            }),
+            h("input", {
+              type: "hidden",
+              name: props.name.replace(/wj$/, "") + "Edit",
+              value: editorContent
+              // value: props.modelValue,
+            }),
+            h("input", {
+              type: "hidden",
+              name: props.name.replace(/wj$/, "") + "wj",
+              value: props.modelValue
+              // value: props.url
+            }),
+            h("input", { type: "hidden", name: "ueditorpath", value: "mswj" }),
+            h("textarea", { id: uniqueId }),
+          ]);
+    },
+  };
+  // 弹窗右边图标
+  const SsFullStyleHeader = {
+    name: "SsFullStyleHeader",
+    props: {
+      title: {
+        type: String,
+        default: "标题",
+      },
+    },
+    emits: ["close"],
+    setup(props, { emit }) {
+      // console.log(props.title)
+      const onClose = () => {
+        emit("close");
+      };
+      const SsIcon = resolveComponent("ss-icon");
+      return () =>
+          h("div", { class: "header-container" }, [
+            h("div", { class: "title" }, props.title),
+            h("div", { class: "handle-bar" }, [
+              h("div", { class: "left-bar" }, [
+                h(SsDialogIcon, { class: "dialog-icon-download" }),
+                h(SsDialogIcon, { class: "dialog-icon-print" }),
+                h(SsDialogIcon, { class: "dialog-icon-setting" }),
+                h(SsDialogIcon, { class: "dialog-icon-collect" }),
+                h(SsDialogIcon, { class: "dialog-icon-help" }),
+                h(SsDialogIcon, { class: "dialog-icon-full-screen" }),
+                h(SsDialogIcon, { class: "dialog-icon-lock" }),
+              ]),
+              h("div", { class: "close-bar", onClick: onClose }, [
+                h(SsDialogIcon, { class: "dialog-icon-close" }),
+              ]),
+            ]),
+          ]);
+    },
+  };
+  // ss-dialog弹窗
+  const SsDialog = {
+    name: "SsDialog",
+    props: {
+      src: {
+        type: String,
+      },
+      headerTitle: {
+        type: String,
+        // required: true,
+        default: "弹窗",
+      },
+      width: {
+        type: String,
+        default: "1400",
+      },
+      height: {
+        type: String,
+        default: "600",
+      },
+      params: {
+        type: Object,
+        default: () => ({}),
+      },
+      zIndex: {
+        type: Number,
+        default: 1000,
+      },
+    },
+    emits: ["close"],
+    setup(props, { slots, emit }) {
+      // 关闭窗口方法
+      const onClose = () => {
+        emit("close");
+      };
+      const showHeader = ref(true);
+      const headerVisible = ref(false);
+      const popupHieght = ref(props.height);
+      // 状态:存储位置信息
+      const position = reactive({
+        // 页面居中
+        x: (window.innerWidth - props.width) / 2,
+        y: (window.innerHeight - popupHieght.value) / 2,
+        isDragging: false,
+        offsetX: 0,
+        offsetY: 0,
+      });
+      // 鼠标按下时设置起始坐标并开始拖拽
+      const startDrag = (event) => {
+        position.isDragging = true;
+        position.offsetX = event.clientX - position.x;
+        position.offsetY = event.clientY - position.y;
+      };
+      // 鼠标移动时更新位置
+      const onDrag = (event) => {
+        if (position.isDragging) {
+          position.x = event.clientX - position.offsetX;
+          position.y = event.clientY - position.offsetY;
+        }
+      };
+      // 鼠标放开时结束拖拽
+      const endDrag = () => {
+        position.isDragging = false;
+      };
+      // 监听来自 iframe 的消息
+      const handleMessage = (event) => {
+        //  顶天立地
+        if (event.data && typeof event.data.hasScrollBar !== "undefined") {
+          if (event.data.hasScrollBar) {
+            //   console.log(event);
+            position.y = 10;
+            showHeader.value = false;
+            headerVisible.value = true;
+            popupHieght.value = window.innerHeight - 20;
+            //   console.log(popupHieght.value);
+            document.querySelector(".body").style.height = "100%";
+            document.querySelector(".body").style.paddingTop = "30px";
+            document.querySelector(".header-container ").style.position =
+                "absolute";
+            document.querySelector(".header-container ").style.zIndex = "10";
+          }
+        }
+      };
+      // 鼠标移入关闭按钮区域时显示头部
+      const onMouseEnterCloseButton = () => {
+        headerVisible.value = false;
+      };
+      // 鼠标移出关闭按钮区域时隐藏头部
+      const onMouseLeaveCloseButton = () => {
+        headerVisible.value = true;
+      };
+      // 在组件挂载时添加全局事件监听器
+      Vue.onMounted(() => {
+        // 如果传过来的高度大于窗口高度,则设置为窗口高度减去20 否则保持传过来的高度
+        popupHieght.value =
+            popupHieght.value > window.innerHeight
+                ? window.innerHeight - 20
+                : popupHieght.value;
+        const container = document.querySelector(".header-container");
+        if (container) {
+          container.addEventListener("mousedown", startDrag);
+        }
+        document.addEventListener("mousemove", onDrag);
+        document.addEventListener("mouseup", endDrag);
+        window.addEventListener("message", handleMessage);
+      });
+
+      // 在组件卸载时移除全局事件监听器
+      Vue.onUnmounted(() => {
+        document.removeEventListener("mousemove", onDrag);
+        document.removeEventListener("mouseup", endDrag);
+        window.removeEventListener("message", handleMessage);
+      });
+      const SsMark = resolveComponent("ss-mark");
+      const SsFullStyleHeader = resolveComponent("ss-full-style-header");
+      // render函数定义组件结构
+      return () =>
+          h(
+              Teleport,
+              { to: "body" }, // 使用 Teleport 将弹窗内容挂载到 body
+              h(SsMark, { }, [
+                h(
+                    "div",
+                    {
+                      class: "popup-container",
+                      style: {
+                        position: "absolute",
+                        left: `${position.x}px`,
+                        top: `${position.y}px`,
+                        width: props.width + "px",
+                        height: popupHieght.value + "px",
+                        zIndex: props.zIndex, // 确保弹窗在最上层
+                      },
+                    },
+                    [
+                      h(SsFullStyleHeader, {
+                        class: "header",
+                        title: props.headerTitle,
+                        onClose: onClose,
+                        onMousedown: startDrag, // 绑定拖动事件
+                        onMouseUp: endDrag,
+                        ...(!showHeader.value && {
+                          onMouseenter: onMouseEnterCloseButton,
+                          onMouseleave: onMouseLeaveCloseButton,
+                        }),
+                        style: {
+                          cursor: position.isDragging ? "grabbing" : "grab",
+                          visibility: headerVisible.value ? "hidden" : "visible",
+                        },
+                      }),
+                      h(
+                          "div",
+                          {
+                            class: "body",
+                            style: {},
+                          },
+                          [
+                            h("iframe", {
+                              src: props.src,
+                              frameborder: 0,
+                              style: { width: "100%", height: "100%" },
+                            }),
+                          ]
+                      ),
+                      headerVisible.value &&
+                      h("div", {
+                        class: "close-button",
+
+                        onMouseenter: onMouseEnterCloseButton,
+                        onMouseleave: onMouseLeaveCloseButton,
+                        style: {
+                          position: "absolute",
+                          top: "0",
+                          right: "0",
+                          // background: 'black',
+                          width: "60px",
+                          height: "60px",
+                          cursor: "pointer",
+                        },
+                      }),
+                    ]
+                ),
+              ])
+          );
+    },
+  };
+  // ss-mark遮罩层
+  const SsMark = {
+    name: "SsMark",
+
+    setup(props, { slots, emit }) {
+      return () =>
+          h("div", { class: "dialog-container" }, [
+            h("div", { class: "mark-content" }, [
+              h("div", { class: "dialog-contianer" }, [
+                slots.default ? slots.default() : "",
+              ]),
+            ]),
+          ]);
+    },
+  };
+  // ss-bottom-button 底部按钮
+  const SsBottomButton = {
+    name: "SsBottomButton",
+    props: {
+      text: {
+        type: String,
+        required: true,
+      },
+      type: {
+        type: String,
+        default: "button",
+      },
+      iconClass: {
+        type: String,
+      },
+      class: {
+        type: String,
+        default: "",
+      },
+      onclick: {
+        type: [Function, String],
+        default: null,
+      },
+    },
+    setup(props, { emit }) {
+      const SsBottomDivIcon = Vue.resolveComponent("ss-bottom-div-icon");
+      return () =>
+          h(
+              "button",
+              {
+                class: props.class,
+                onClick: (e) => {
+                  e.stopPropagation();
+                  if (props.onclick) {
+                    // 如果是函数直接调用
+                    if (typeof props.onclick === "function") {
+                      props.onclick(e);
+                    } else if (typeof props.onclick === "string") {
+                      // 如果是字符串,使用直接的方法执行
+                      // 临时存储按钮元素到全局变量
+                      window.__ss_current_button = e.currentTarget;
+
+                      // 直接执行代码,使用eval以保留原始上下文
+                      try {
+                        eval(props.onclick);
+                      } finally {
+                        // 清理全局变量
+                        delete window.__ss_current_button;
+                      }
+                    }
+                  }
+                },
+                type: props.type,
+              },
+              [
+                h("span", null, [
+                  h(SsBottomDivIcon, {
+                    class: props.iconClass,
+                  }),
+                ]),
+                h("span", null, props.text),
+              ]
+          );
+    },
+  };
+  // ss-search搜索框
+  const SsSearch = {
+    name: "SsSearch",
+    props: {
+      theme: {
+        type: String,
+        default: "light",
+        validator: function (value) {
+          return ["dark", "light"].includes(value);
+        },
+      },
+      placeholder: {
+        type: String,
+        default: "请输入搜索条件",
+      },
+    },
+    setup(props, { emit }) {
+      const onClick = () => {
+        console.log("Search clicked");
+        emit("click");
+      };
+      const SsIcon = Vue.resolveComponent("ss-icon");
+      return () =>
+          Vue.h(
+              "div",
+              {
+                class: ["search-container", props.theme],
+                onClick: onClick,
+              },
+              [
+                Vue.h("input", {
+                  placeholder: props.placeholder,
+                  disabled: true,
+                }),
+                Vue.h(SsIcon, {
+                  name: "search-result",
+                  size: "20px",
+                }),
+              ]
+          );
+    },
+  };
+  // ss-cart-item 菜单页面的卡片 左右结构
+  const SsCartItem = {
+    name: "SsCartItem",
+    props: {
+      active: Boolean,
+      item: {
+        type: Object,
+        default: () => ({
+          thumb: "images/example/project-img.png",
+          title: "广州(国际)科技成果转化天河基地专",
+          description: "佳能中国广州分公司",
+          all: 50,
+          finish: 5,
+        }),
+      },
+    },
+    setup(props, { emit }) {
+      const item = props.item;
+
+      const itemWidth = Vue.computed(() => {
+        const containerWidth =
+            document.body.clientWidth || document.body.scrollWidth - 520;
+        const halfWidth = containerWidth / 2;
+        if (halfWidth < 480) {
+          return Math.min(containerWidth, 702) + "px";
+        } else {
+          return Math.min(halfWidth, 702) + "px";
+        }
+      });
+
+      const onItemClick = (e) => {
+        emit("click", e);
+      };
+
+      return {
+        item,
+        itemWidth,
+        onItemClick,
+      };
+    },
+    render() {
+      const SsIcon = Vue.resolveComponent("ss-icon");
+      return Vue.h(
+          "div",
+          {
+            class: { "item-container": true, active: this.active },
+            onClick: this.onItemClick,
+            style: { width: this.itemWidth },
+          },
+          [
+            Vue.h("div", { class: "header" }, [
+              Vue.h(SsIcon, { name: "setting", size: "20px" }),
+            ]),
+            Vue.h("div", { class: "body" }, [
+              Vue.h("div", { class: "left" }, [
+                Vue.h("img", {
+                  src: this.item.thumb,
+                  alt: "Thumbnail",
+                  class: "imgUnHandle",
+                  style: { "object-fit": "cover", width: "100%", height: "100%" },
+                }),
+              ]),
+              Vue.h("div", { class: "right" }, [
+                Vue.h("div", { class: "title" }, this.item.title),
+                Vue.h("div", { class: "desc" }, this.item.description),
+                Vue.h("div", { class: "progress" }, [
+                  Vue.h(
+                      "div",
+                      {
+                        style: {
+                          width: `${(this.item.finish / this.item.all) * 100}%`,
+                        },
+                      },
+                      [Vue.h("div", `${this.item.finish}/${this.item.all}`)]
+                  ),
+                ]),
+              ]),
+            ]),
+          ]
+      );
+    },
+  };
+  // ss-cart-item2 菜单页面的卡片 上下结构
+  const SsCartItem2 = {
+    name: "SsCartItem2",
+    props: {
+      active: Boolean,
+      item: {
+        type: Object,
+        default: () => ({
+          thumb: "images/example/project-img.png",
+          title: "广州(国际)科技成果转化天河基地专",
+          description: "佳能中国广州分公司",
+          all: 50,
+          finish: 5,
+        }),
+      },
+    },
+    setup(props, { emit }) {
+      const item = props.item;
+      const itemWidth = Vue.computed(() => {
+        const containerWidth =
+            document.body.clientWidth || document.body.scrollWidth - 520;
+        const halfWidth = containerWidth / 2;
+        if (halfWidth < 480) {
+          return Math.min(containerWidth, 702) + "px";
+        } else {
+          return Math.min(halfWidth, 702) + "px";
+        }
+      });
+
+      const onItemClick = (e) => {
+        emit("click", e);
+      };
+
+      return {
+        item,
+        itemWidth,
+        onItemClick,
+      };
+    },
+
+    render() {
+      const SsIcon = Vue.resolveComponent("ss-icon");
+      return Vue.h(
+          "div",
+          {
+            class: { "item-container2": true, active: this.active },
+            onClick: this.onItemClick,
+            style: { width: this.itemWidth },
+          },
+          [
+            Vue.h("div", { class: "action-bar" }, [
+              Vue.h(SsIcon, { name: "setting", size: "20px" }),
+            ]),
+            Vue.h("div", { class: "header" }, [
+              Vue.h("div", { class: "title" }, `${this.item.title}`),
+            ]),
+            Vue.h("div", { class: "body" }, [
+              Vue.h("div", { class: "left" }, [
+                Vue.h("img", {
+                  src: this.item.thumb,
+                  alt: "Thumbnail",
+                  class: "imgUnHandle",
+                  style: { "object-fit": "cover", width: "100%", height: "100%" },
+                }),
+              ]),
+              Vue.h("div", { class: "right" }, [
+                Vue.h("div", { class: "content" }, this.item.description),
+                Vue.h("div", { class: "tip" }, [
+                  Vue.h("div", { class: "progress" }, [
+                    Vue.h(
+                        "div",
+                        {
+                          style: {
+                            width: `${(this.item.finish / this.item.all) * 100}%`,
+                          },
+                        },
+                        [Vue.h("div", `${this.item.finish}/${this.item.all}`)]
+                    ),
+                  ]),
+                ]),
+              ]),
+            ]),
+          ]
+      );
+    },
+  };
+  // ss-list-card 通用列表卡片
+  const SsListCard = {
+    name: "SsListCard",
+    props: {
+      item: {
+        type: Object,
+        required: true,
+      },
+    },
+    emits: ["click", "change"],
+    setup(props, { emit }) {
+      const item = props.item;
+      const itemWidth = Vue.computed(() => {
+        const containerWidth =
+            document.body.clientWidth || document.body.scrollWidth;
+        if (containerWidth > 1200) {
+          return "30%";
+        }
+        return "45%";
+      });
+      const onItemClick = (e) => {
+        // 清除所有类型卡片的 active 状态
+        const allListCards = document.querySelectorAll(
+            ".knowledge-item-container"
+        );
+        const allFolderCards = document.querySelectorAll(".ss-folder-list");
+
+        allListCards.forEach((card) => card.classList.remove("active"));
+        allFolderCards.forEach((card) => card.classList.remove("active"));
+
+        // 设置当前项的 active 状态
+        e.currentTarget.classList.add("active");
+        props.item.onclick();
+      };
+      const onItemChange = (e, icon, index) => {
+        e.stopPropagation(); // 阻止事件冒泡到卡片
+        props.item.buttons[0].onclick();
+        // emit("change", { item: props.item, icon, index });
+      };
+      return {
+        item,
+        itemWidth,
+        onItemClick,
+        onItemChange,
+      };
+    },
+
+    data() {
+      return {
+        showButtons: false,
+      };
+    },
+
+    render() {
+      const SsCartListIcon = Vue.resolveComponent("ss-cart-list-icon");
+      return Vue.h(
+          "div",
+          {
+            class: { "knowledge-item-container": true, active: this.item.active },
+            onClick: this.onItemClick,
+            style: { width: this.itemWidth },
+          },
+          [
+            this.item?.buttons?.length > 0 &&
+            Vue.h(
+                "div",
+                {
+                  class: "header",
+                  onMouseenter: () => (this.showButtons = true),
+                  onMouseleave: () => (this.showButtons = false),
+                  onClick: (e) => this.onItemChange(e, this.item.buttons[0], 0),
+                },
+                [
+                  // 只在有按钮时渲染设置图标
+                  // this.item?.buttons?.length > 0 &&
+                  Vue.h("div", {
+                    class: "cart-list-setting cart-list-icon",
+                    title: this.item?.buttons?.[0]?.title,
+                  }),
+
+                  // 鼠标移入时显示按钮列表,与图标同级
+                  // this.item?.buttons?.length > 0 &&
+                  this.showButtons &&
+                  this.item?.buttons?.length > 1 &&
+                  Vue.h(
+                      "div",
+                      {
+                        class: "cart-list-button-popup",
+                      },
+                      this.item.buttons.map((btn) =>
+                          Vue.h(
+                              "div",
+                              {
+                                onClick: (e) => {
+                                  e.stopPropagation();
+                                  btn.onclick?.();
+                                },
+                              },
+                              [
+                                // 如果有 class,显示对应的图标
+                                btn.class &&
+                                Vue.h(SsCartListIcon, {
+                                  class: [btn.class],
+                                }),
+                                // 显示按钮文本
+                                Vue.h("span", null, btn.title),
+                              ]
+                          )
+                      )
+                  ),
+                ]
+            ),
+
+            Vue.h("div", { class: "body" }, [
+              Vue.h("div", { class: "box-header" }, [
+                Vue.h("div", `${this.item.title}`),
+              ]),
+              Vue.h(
+                  "div",
+                  {
+                    class: !this.item.thumb ? "no-thumb box-body" : "box-body",
+                  },
+                  [
+                    this.item.thumb
+                        ? Vue.h("div", { class: "left" }, [
+                          Vue.h("img", {
+                            src: this.item.thumb,
+                            alt: "Thumbnail",
+                            class: "imgUnHandle",
+                            style: {
+                              "object-fit": "cover",
+                              width: "100%",
+                              height: "100%",
+                            },
+                          }),
+                        ])
+                        : null,
+                    Vue.h("div", { class: "right" }, [
+                      ...this.item.tags.map((tag) => {
+                        const [key, value] = Object.entries(tag)[0];
+                        return Vue.h(
+                            "div",
+                            {
+                              class: "title",
+                              title: `${key}: ${value}`,
+                            },
+                            `${key}: ${value}`
+                        );
+                      }),
+                    ]),
+                  ]
+              ),
+            ]),
+          ]
+      );
+    },
+  };
+  // ss-folder-card 文件夹卡片
+  const SsFolderCard = {
+    name: "SsFolderCard",
+    props: {
+      item: {
+        type: Object,
+        required: true,
+      },
+    },
+    data() {
+      return {
+        showButtons: false,
+      };
+    },
+    emits: ["click", "change"],
+    setup(props, { emit }) {
+      const item = props.item;
+      const showChildren = ref(false);
+      const eventBus = window.parent.sharedEventBus;
+
+      const itemWidth = Vue.computed(() => {
+        const containerWidth =
+            document.body.clientWidth || document.body.scrollWidth;
+        return containerWidth > 1200 ? "45%" : "90%";
+      });
+      onMounted(() => {
+        eventBus.subscribe("folderPath", (path) => {
+          const currentPath = path || [];
+          // 如果当前文件夹不在路径中,则销毁视图
+          if (
+              !currentPath.some((item) => item.folder.title === props.item.title)
+          ) {
+            showChildren.value = false;
+          }
+        });
+      });
+      const onItemClick = (e) => {
+        if (e && e.stopPropagation) {
+          e.stopPropagation();
+        }
+        // 单击只处理 active 状态
+        if (e && e.currentTarget) {
+          const allListCards = document.querySelectorAll(
+              ".knowledge-item-container"
+          );
+          const allFolderCards = document.querySelectorAll(".ss-folder-list");
+
+          allListCards.forEach((card) => card.classList.remove("active"));
+          allFolderCards.forEach((card) => card.classList.remove("active"));
+
+          e.currentTarget.classList.add("active");
+        } else {
+          // 如果是数据对象,需要找到对应的 DOM 元素
+          const allListCards = document.querySelectorAll(
+              ".knowledge-item-container"
+          );
+          const allFolderCards = document.querySelectorAll(".ss-folder-list");
+          allListCards.forEach((card) => card.classList.remove("active"));
+          allFolderCards.forEach((card) => card.classList.remove("active"));
+          // 找到标题匹配的文件夹元素
+          const targetFolder = Array.from(allFolderCards).find((card) =>
+              card.textContent.includes(e.title)
+          );
+
+          if (targetFolder) {
+            targetFolder.classList.add("active");
+          }
+        }
+        emit("click", item);
+      };
+      // 修改双击处理函数
+      const handleFolderDblClick = (folder, e) => {
+        if (e) e.stopPropagation();
+        if (folder.children?.length) {
+          showChildren.value = true;
+          const pathInfo = {
+            title: folder.title,
+            folder: folder,
+          };
+          const currentPath = eventBus.getState("folderPath") || [];
+          if (!currentPath.some((item) => item.title === folder.title)) {
+            eventBus.publish("folderPath", [...currentPath, pathInfo]);
+          }
+        }
+      };
+      const onItemChange = (e, icon, index) => {
+        e.stopPropagation();
+        props.item.buttons[0].onclick();
+        // emit("change", { item: props.item, icon, index });
+      };
+      return {
+        item,
+        itemWidth,
+        showChildren,
+        onItemClick,
+        onItemChange,
+        handleFolderDblClick,
+      };
+    },
+    render() {
+      const SsCartListIcon = Vue.resolveComponent("ss-cart-list-icon");
+      if (this.showChildren) {
+        return h(SsFolderCartView, {
+          folder: this.item,
+        });
+      }
+      return Vue.h(
+          "div",
+          {
+            class: { "ss-folder-list": true, active: this.item.active },
+            onClick: (e) => {
+              e.stopPropagation();
+              this.onItemClick(e);
+            },
+            onDblclick: (e) => this.handleFolderDblClick(this.item, e),
+            style: { width: this.itemWidth },
+          },
+          [
+            // 文件夹特有的装饰元素
+            Vue.h("div", { class: "ss-folder-list-trapezoid" }),
+            Vue.h("div", { class: "ss-folder-list-top-transparent" }),
+            Vue.h("div", { class: "ss-folder-list-top" }),
+            Vue.h("div", { class: "ss-folder-list-right" }),
+
+            // header 部分(按钮)
+            this.item?.buttons?.length > 0 &&
+            Vue.h(
+                "div",
+                {
+                  class: "header",
+                  onMouseenter: () => (this.showButtons = true),
+                  onMouseleave: () => (this.showButtons = false),
+                  onClick: (e) => this.onItemChange(e, this.item.buttons[0], 0),
+                },
+                [
+                  // this.item?.buttons?.length > 0 &&
+                  Vue.h("div", {
+                    class: "cart-list-setting cart-list-icon",
+                    title: this.item?.buttons?.[0]?.title,
+                  }),
+
+                  // this.item?.buttons?.length > 0 &&
+                  this.showButtons &&
+                  this.item?.buttons?.length > 1 &&
+                  Vue.h(
+                      "div",
+                      {
+                        class: "cart-list-button-popup",
+                      },
+                      this.item.buttons.map((btn) =>
+                          Vue.h(
+                              "div",
+                              {
+                                onClick: (e) => {
+                                  e.stopPropagation();
+                                  btn.onclick?.();
+                                },
+                              },
+                              [
+                                btn.class &&
+                                Vue.h(SsCartListIcon, {
+                                  class: [btn.class],
+                                }),
+                                Vue.h("span", null, btn.title),
+                              ]
+                          )
+                      )
+                  ),
+                ]
+            ),
+            // body 部分
+            Vue.h("div", { class: "body" }, [
+              Vue.h("div", { class: "box-header" }, [
+                Vue.h("div", null, this.item.title),
+              ]),
+              Vue.h(
+                  "div",
+                  {
+                    class: !this.item.thumb ? "no-thumb box-body" : "box-body",
+                  },
+                  [
+                    this.item.thumb
+                        ? Vue.h("div", { class: "left" }, [
+                          Vue.h("img", {
+                            src: this.item.thumb,
+                            alt: "Thumbnail",
+                            class: "imgUnHandle",
+                            style: {
+                              "object-fit": "cover",
+                              width: "100%",
+                              height: "100%",
+                            },
+                          }),
+                        ])
+                        : null,
+                    Vue.h("div", { class: "right" }, [
+                      ...this.item.tags.map((tag) => {
+                        const [key, value] = Object.entries(tag)[0];
+                        return Vue.h(
+                            "div",
+                            {
+                              class: "title",
+                              title: `${key}: ${value}`,
+                            },
+                            `${key}: ${value}`
+                        );
+                      }),
+                    ]),
+                  ]
+              ),
+            ]),
+          ]
+      );
+    },
+  };
+  // SsFolderCartView 组件 - 用于显示文件夹内容
+  const SsFolderCartView = {
+    name: "SsFolderCartView",
+    props: {
+      folder: {
+        type: Object,
+        required: true,
+      },
+    },
+    emits: ["click"],
+    setup(props, { emit }) {
+      const eventBus = window.parent.sharedEventBus;
+      const currentFolder = ref(props.folder);
+      const showChildren = ref(false);
+
+      const onItemClick = (e) => {
+        if (e && e.stopPropagation) {
+          e.stopPropagation();
+        }
+        // 单击只处理 active 状态
+        if (e && e.currentTarget) {
+          const allListCards = document.querySelectorAll(
+              ".knowledge-item-container"
+          );
+          const allFolderCards = document.querySelectorAll(".ss-folder-list");
+
+          allListCards.forEach((card) => card.classList.remove("active"));
+          allFolderCards.forEach((card) => card.classList.remove("active"));
+
+          e.currentTarget.classList.add("active");
+        } else {
+          // 如果是数据对象,需要找到对应的 DOM 元素
+          const allListCards = document.querySelectorAll(
+              ".knowledge-item-container"
+          );
+          const allFolderCards = document.querySelectorAll(".ss-folder-list");
+
+          allListCards.forEach((card) => card.classList.remove("active"));
+          allFolderCards.forEach((card) => card.classList.remove("active"));
+
+          // 找到标题匹配的文件夹元素
+          const targetFolder = Array.from(allFolderCards).find((card) =>
+              card.textContent.includes(e.title)
+          );
+
+          if (targetFolder) {
+            targetFolder.classList.add("active");
+          }
+        }
+        emit("click", props.folder);
+      };
+      const handleFolderDblClick = (folder, e) => {
+        if (e) e.stopPropagation();
+        if (folder.children?.length) {
+          showChildren.value = true;
+          const pathInfo = {
+            title: folder.title,
+            folder: folder,
+          };
+          const currentPath = eventBus.getState("folderPath") || [];
+          if (!currentPath.some((item) => item.title === folder.title)) {
+            eventBus.publish("folderPath", [...currentPath, pathInfo]);
+            currentFolder.value = folder;
+          }
+        }
+      };
+
+      const goBack = (targetFolder) => {
+        if (targetFolder === null) {
+          // 返回根目录
+          eventBus.publish("folderPath", []);
+        } else {
+          currentFolder.value = targetFolder;
+        }
+      };
+
+      return {
+        currentFolder,
+        showChildren,
+        onItemClick,
+        handleFolderDblClick,
+        goBack,
+      };
+    },
+
+    render() {
+      return h(
+          "div",
+          {
+            class: "page-container",
+            style: {
+              position: "fixed",
+              top: 0,
+              left: 0,
+              width: "100%",
+              height: "100%",
+              background: "var(--lightgray)",
+              padding: "20px 0",
+              zIndex: 1000,
+            },
+          },
+          [
+            // 搜索栏
+            h("div", { class: "search-bar" }, [
+              h("div", { class: "search-bar-contaienr" }, [
+                h(SsBreadcrumb, {
+                  level: {
+                    onBack: this.goBack,
+                  },
+                }),
+              ]),
+            ]),
+
+            // 内容区域
+            h(
+                "div",
+                {
+                  class: "content-area item-content-area",
+                  style: { gap: "20px" },
+                },
+                [
+                  ...(this.currentFolder.children || []).map((child, index) =>
+                      h(child.children ? SsFolderCard : SsListCard, {
+                        key: index,
+                        item: child,
+                        onClick: (e) => this.onItemClick(e),
+                        onDblclick: (e) => this.handleFolderDblClick(child, e),
+                      })
+                  ),
+                ]
+            ),
+          ]
+      );
+    },
+  };
+
+  // ss-page分页
+  const SsPage = {
+    name: "SsPage",
+    props: {
+      total: {
+        type: Number,
+        required: true,
+      },
+
+      size: {
+        type: Number,
+        default: 10,
+      },
+      page: {
+        type: Number,
+        default: 1,
+      },
+      onChange: {
+        type: Function,
+        default: () => {},
+      },
+    },
+    setup(props) {
+      const totalItems = ref(props.total); // 总条目数
+      const totalPages = ref(Math.ceil(props.total / props.size));
+      const currentPage = ref(props.page); // 当前页码
+
+      // 计算显示的信息
+      const pageInfo = ref(
+          `共${totalItems.value}条,第 ${currentPage.value}/${totalPages.value} 页`
+      );
+
+      // 上一页的逻辑
+      const goToPreviousPage = (e) => {
+        e.preventDefault(); // 阻止默认行为
+        if (currentPage.value > 1) {
+          currentPage.value -= 1;
+          updatePageInfo();
+          props.onChange?.({
+            pageNo: currentPage.value, // 当前页码
+            rowNumPer: props.size, // 每页条数
+            rowNum: props.total, // 总记录数
+          });
+        }
+      };
+
+      // 下一页的逻辑
+      const goToNextPage = (e) => {
+        e.preventDefault(); // 阻止默认行为
+        if (currentPage.value < totalPages.value) {
+          currentPage.value += 1;
+          updatePageInfo();
+          props.onChange?.({
+            pageNo: currentPage.value, // 当前页码
+            rowNumPer: props.size, // 每页条数
+            rowNum: props.total, // 总记录数
+          });
+        }
+      };
+
+      // 更新页码信息的函数
+      const updatePageInfo = () => {
+        pageInfo.value = `共${totalItems.value}条,第 ${currentPage.value}/${totalPages.value} 页`;
+      };
+
+      return {
+        pageInfo,
+        totalPages,
+        goToPreviousPage,
+        goToNextPage,
+      };
+    },
+
+    render(props, { slots, emit }) {
+      return Vue.h("div", { class: "pager-container" }, [
+        Vue.h("input", { type: "hidden", name: "rowNum", value: props.total }),
+        Vue.h("input", {
+          type: "hidden",
+          name: "rowNumPer",
+          value: props.size,
+        }),
+        Vue.h("input", {
+          type: "hidden",
+          name: "pageCount",
+          value: this.totalPages,
+        }),
+        Vue.h("input", { type: "hidden", name: "pageNo", value: props.page }),
+        Vue.h("div", { class: "pager-content" }, [
+          Vue.h("div", { class: "info" }, this.pageInfo),
+          Vue.h(
+              "div",
+              { class: "btn" },
+              Vue.h(
+                  "button",
+                  { onClick: (e) => this.goToPreviousPage(e) },
+                  "上一页"
+              )
+          ),
+          Vue.h(
+              "div",
+              { class: "btn" },
+              Vue.h("button", { onClick: (e) => this.goToNextPage(e) }, "下一页")
+          ),
+        ]),
+      ]);
+    },
+  };
+  // ss-right-info 一级页面右边栏
+  const SSRightInfo = {
+    name: "SSRightInfo",
+    setup() {
+      // 初始化响应式数据
+      const item = ref({
+        thumb: "images/example/project-img.png", // 更换为适合你项目的实际路径
+        title: "工业和信息化产业高质量发展资金",
+      });
+
+      return {
+        item,
+      };
+    },
+    render() {
+      return Vue.h("div", { class: "info-container" }, [
+        Vue.h("div", { class: "header" }, [
+          Vue.h("div", [
+            Vue.h("img", {
+              src: this.item.thumb,
+              class: "imgUnHandle",
+              style: { "object-fit": "cover", width: "100%", height: "100%" },
+            }), // 将 ImageViewer 替换为 img 标签
+          ]),
+          Vue.h("div", [Vue.h("div", this.item.title)]),
+        ]),
+        Vue.h("div", { class: "section-container" }, [
+          Vue.h("div", { class: "section" }, [
+            Vue.h("div", { class: "title" }, "合同"),
+            Vue.h("div", { class: "text" }, "合同总金额:42,399,320"),
+            Vue.h(
+                "div",
+                { class: "a" },
+                "《工业和信息化产业高质量发展资金补助合同》"
+            ),
+          ]),
+          Vue.h("div", { class: "section" }, [
+            Vue.h("div", { class: "title" }, "发票"),
+            Vue.h("div", { class: "text" }, "应开发票总额:42,399,320"),
+            Vue.h("div", { class: "text" }, "已开发票金额:17,235,345"),
+            Vue.h("div", { class: "text" }, "未开发票金额:25,163,975"),
+          ]),
+          Vue.h("div", { class: "section" }, [
+            Vue.h("div", { class: "title" }, "项目组成员"),
+            Vue.h("div", { class: "text" }, "我司:3人"),
+            Vue.h("div", { class: "text" }, "对方:2人"),
+            Vue.h("div", { class: "text" }, "项目负责人:张三"),
+          ]),
+          Vue.h("div", { class: "section" }, [
+            Vue.h("div", { class: "title" }, "采购"),
+            Vue.h("div", { class: "text" }, "总额:999,320"),
+            Vue.h("div", { class: "text" }, "已付金额:335,345"),
+            Vue.h("div", { class: "text" }, "未付金额:663,975"),
+          ]),
+        ]),
+      ]);
+    },
+  };
+  //
+  const SsSuccessPopup = {
+    name: "SsSuccessPopup",
+    props: {
+      right: {
+        type: String,
+        default: "20px",
+      },
+      bottom: {
+        type: String,
+        default: "calc(100% + 5px)",
+      },
+    },
+    setup(props, { expose }) {
+      // 响应式状态:是否可见
+      const visible = ref(false);
+
+      // 计算样式
+      const style = computed(() => {
+        return {
+          "--message-dialog-right": props.right,
+          "--message-dialog-bottom": props.bottom,
+        };
+      });
+
+      // 显示对话框的方法
+      const show = () => {
+        visible.value = true;
+      };
+
+      // 隐藏对话框的方法
+      const hide = () => {
+        visible.value = false;
+      };
+
+      // 将方法暴露给外部使用
+      expose({ show, hide });
+
+      // 返回渲染函数
+      return () => {
+        if (!visible.value) return null;
+        const SsIcon = resolveComponent("ss-icon");
+        return h(
+            "div",
+            {
+              class: "success-popup",
+              style: style.value,
+              onClick: (e) => e.stopPropagation(),
+            },
+            [
+              h("div", { class: "left" }, [
+                h("div", { class: "icon" }, [
+                  h(SsIcon, { name: "check", size: "36px" }),
+                ]),
+              ]),
+              h("div", { class: "right" }, [
+                h("div", { class: "title" }, "提交成功"),
+                h("div", { class: "desc" }, "您的信息已成功提交。"),
+              ]),
+            ]
+        );
+      };
+    },
+  };
+  const SsErrorDialog = {
+    name: "SsErrorDialog",
+    setup(props, { emit }) {
+      const visible = ref(false);
+
+      const style = computed(() => {
+        return {};
+      });
+
+      const show = () => {
+        visible.value = true;
+      };
+
+      const hide = () => {
+        visible.value = false;
+      };
+
+      const onBack = () => {
+        emit("back");
+        hide();
+      };
+
+      return {
+        visible,
+        style,
+        show,
+        hide,
+        onBack,
+      };
+    },
+    render() {
+      const SsIcon = resolveComponent("ss-icon");
+      return this.visible
+          ? h(
+              "div",
+              {
+                class: "errorDialog",
+                style: this.style,
+                onClick: (event) => event.stopPropagation(),
+              },
+              [
+                h("div", { class: "body" }, [
+                  h("div", { class: "left" }, [
+                    h("div", { class: "icon" }, [
+                      h(SsIcon, { name: "close", size: "36px" }),
+                    ]),
+                  ]),
+                  h("div", { class: "right" }, [
+                    h("div", { class: "title" }, "操作失败"),
+                    h("div", { class: "desc" }, "请点击返回以继续。"),
+                  ]),
+                ]),
+                h("div", { class: "footer" }, [
+                  h("div", { class: "left" }),
+                  h("div", { class: "right" }, [
+                    h(
+                        "div",
+                        {
+                          class: "btn",
+                          onClick: this.onBack,
+                        },
+                        [h(SsIcon, { name: "arrow-left-line" }), h("div", "返回")]
+                    ),
+                  ]),
+                ]),
+              ]
+          )
+          : null;
+    },
+  };
+  /**
+   * 审核链条
+   * @name ss-verify
+   * @param { Array } verify-list 审核节点列表
+   * @property { Array } verify-list 审核节点列表
+   * @example <ss-verify :verify-list="verifyList"></ss-verify>
+   * verify-list [
+   *    {
+   *        groupName: "",  // 群组名称
+   *        open: true, // 默认是否展开
+   *        children:[ //群组里的人员
+   *           {
+   *            thumb: "images/example/user-4.png", // 头像
+   *             name: "李丽思 ", // 姓名
+   *             role: "人事处处长",  // 角色
+   *             description: "同意。",  // 审核意见
+   *             time: "09:38 08/11", // 审核时间
+   *             video: false,  // false不显示/true显示 视频icon
+   *             link: false,  // false不显示/true显示 链接icon 后续应该是附件
+   *           }
+   *        ]
+   *    }
+   *  ]
+   */
+  const SsVerify = {
+    name: "SsVerify",
+    props: {
+      verifyList: {
+        type: Array,
+        required: true,
+      },
+    },
+    setup(props) {
+      const toggleOpen = (item) => {
+        item.open = !item.open;
+      };
+      onMounted(() => {
+        setTimeout(() => {
+          const lastOpenGroup = document.querySelector(".group-item-last-open");
+          console.log("lastOpenGroup", lastOpenGroup);
+          if (lastOpenGroup) {
+            const nodes = $(lastOpenGroup).find(".verify-node-container");
+            if (nodes.length) {
+              let totalHeight = 0;
+              const gudingHeight = 100;
+
+              if (nodes.length === 1) {
+                totalHeight = gudingHeight;
+              } else {
+                // 累加除最后一个节点外的所有节点高度
+                for (let i = 0; i < nodes.length - 1; i++) {
+                  totalHeight += $(nodes[i]).outerHeight();
+                }
+                totalHeight += gudingHeight;
+              }
+
+              console.log("节点信息:", {
+                节点总数: nodes.length,
+                计算后的高度: totalHeight,
+              });
+
+              lastOpenGroup.style.setProperty(
+                  "--group-line-height",
+                  `${totalHeight}px`
+              );
+            }
+          }
+        }, 0);
+      });
+      return {
+        toggleOpen,
+      };
+    },
+    render() {
+      const SsIcon = resolveComponent("ss-icon");
+      const SsCommonIcon = resolveComponent("ss-common-icon");
+      const SsVerifyNode = resolveComponent("ss-verify-node");
+      return h(
+          "div",
+          { class: "verify-nodes" },
+          this.verifyList.map((item, i) =>
+              h(
+                  "div",
+                  {
+                    key: i,
+                    class: {
+                      "group-item": true,
+                      "group-item-last-open":
+                          i === this.verifyList.length - 1 && item.open,
+                    },
+                  },
+                  [
+                    h(
+                        "div",
+                        {
+                          class: "group-item-title",
+                          onClick: () => this.toggleOpen(item),
+                        },
+                        [
+                          h("div", { class: "icon" }, [
+                            item.open
+                                ? h(SsCommonIcon, { class: "common-icon-folder-open" })
+                                : h(SsCommonIcon, { class: "common-icon-folder-close" }),
+                            h(
+                                "div",
+                                {
+                                  class: "num",
+                                  style: { top: item.open ? "60%" : "55%" },
+                                },
+                                item.children?.length || 0
+                            ),
+                          ]),
+                          h("div", { class: "name" }, item.groupName),
+                        ]
+                    ),
+                    item.open && item.children?.length > 0
+                        ? h(
+                            "div",
+                            { class: "group-item-children" },
+                            item.children.map((citem, j) =>
+                                h(SsVerifyNode, {
+                                  key: j,
+                                  item: citem,
+                                  // isGroup: i + 1 !== this.verifyList.length,
+                                  isGroup: true,
+                                })
+                            )
+                        )
+                        : null,
+                  ]
+              )
+          )
+      );
+    },
+  };
+
+  /**
+   * 审核页面的审核节点
+   * @name ss-verify-node
+   * @param {Object} item 审核节点信息
+   * @param {Boolean} isGroup 是否为分组节点
+   */
+  const SsVerifyNode = {
+    name: "SsVerifyNode",
+    props: {
+      item: {
+        type: Object,
+        required: true,
+      },
+      isGroup: {
+        type: Boolean,
+        default: false,
+      },
+    },
+    render() {
+      const SsIcon = resolveComponent("ss-icon");
+      const SsCommonIcon = resolveComponent("ss-common-icon");
+      return Vue.h("div", { class: "verify-node-container" }, [
+        Vue.h("div", { class: "info" }, [
+          Vue.h("div", { class: "avatar" }, [
+            Vue.h("img", {
+              src: this.item.thumb,
+              style: {
+                width: "50px",
+                height: "50px",
+                borderRadius: "50%",
+              },
+            }),
+          ]),
+          Vue.h("div", { class: "desc" }, [
+            Vue.h("div", this.item.name),
+            Vue.h("div", this.item.role),
+          ]),
+          Vue.h("div", { class: "link" }, [
+            Vue.h("div", [
+              this.item.video
+                  ? Vue.h(SsCommonIcon, { class: "common-icon-video" })
+                  : null,
+              this.item.link
+                  ? Vue.h(SsCommonIcon, {
+                    class: "common-icon-paper-clip",
+                  })
+                  : null,
+            ]),
+          ]),
+        ]),
+        Vue.h(
+            "div",
+            {
+              class: {
+                description: true,
+                link: this.isGroup,
+              },
+              attrs: { "data-num": "3" },
+            },
+            [Vue.h("div", this.item.description)]
+        ),
+        Vue.h("div", { class: "time" }, this.item.time),
+      ]);
+    },
+  };
+  /**
+   * 智能识别图片的左侧图片播放 可以放大缩小旋转图片
+   * @name ss-orc-img-box
+   * @param { Object } image-obj 包含图片的url, 和图片的名称
+   *
+   */
+  const SsOrcImgBox = {
+    name: "SsOrcImgBox",
+    props: {
+      imageObj: {
+        type: Object,
+        required: true,
+      },
+    },
+    setup(props) {
+      const zoom = ref(1);
+      const rotation = ref(0);
+      const containerWidth = ref(0);
+      const containerHeight = ref(0);
+      const container = ref(null);
+      const imgPosition = ref({ x: 0, y: 0 });
+      const isDragging = ref(false);
+      const lastMousePosition = ref({ x: 0, y: 0 });
+      const imgStyle = computed(() => ({
+        width: `${zoom.value * 100}%`,
+        height: `${zoom.value * 100}%`,
+        transform: `rotate(${rotation.value}deg) translate(${imgPosition.value.x}px, ${imgPosition.value.y}px)`,
+        transformOrigin: "center center",
+        cursor: isDragging.value ? "grabbing" : "grab",
+      }));
+
+      const resetZoom = () => {
+        zoom.value = 1;
+        rotation.value = rotation.value + 90;
+        imgPosition.value = { x: 0, y: 0 };
+      };
+
+      const handleRangeChange = (event) => {
+        const value = event.target.value / 50; // 0 到 100 映射到 0 到 2 的缩放
+        zoom.value = Math.max(value, 0.1); // 设置最小缩放值为 0.1
+      };
+      const updateImgBoxDimensions = () => {
+        if (container.value) {
+          containerWidth.value = container.value.clientWidth;
+          containerHeight.value = container.value.clientHeight;
+        }
+      };
+      const onMouseDown = (event) => {
+        isDragging.value = true;
+        lastMousePosition.value = { x: event.clientX, y: event.clientY };
+      };
+
+      const onMouseMove = (event) => {
+        if (isDragging.value) {
+          const dx = event.clientX - lastMousePosition.value.x;
+          const dy = event.clientY - lastMousePosition.value.y;
+
+          // 防止旋转后拖动的x,y反转
+          // 首先将当前旋转角度从度数转换为弧度,因为 JavaScript 的 Math 库使用弧度
+          const angle = rotation.value * (Math.PI / 180);
+          // 使用基本的二维旋转矩阵将原始位移 dx 和 dy 转换为旋转后的位移 rotatedDx 和 rotatedDy。
+          const rotatedDx = dx * Math.cos(angle) + dy * Math.sin(angle);
+          const rotatedDy = dy * Math.cos(angle) - dx * Math.sin(angle);
+
+          imgPosition.value = {
+            x: imgPosition.value.x + rotatedDx,
+            y: imgPosition.value.y + rotatedDy,
+          };
+          lastMousePosition.value = { x: event.clientX, y: event.clientY };
+        }
+      };
+
+      const onMouseUp = () => {
+        isDragging.value = false;
+      };
+      onMounted(() => {
+        nextTick(() => {
+          updateImgBoxDimensions();
+          window.addEventListener("resize", updateImgBoxDimensions);
+          window.addEventListener("mousemove", onMouseMove);
+          window.addEventListener("mouseup", onMouseUp);
+        });
+      });
+
+      return {
+        zoom,
+        rotation,
+        container,
+        imgStyle,
+        resetZoom,
+        handleRangeChange,
+        containerWidth,
+        containerHeight,
+        onMouseDown,
+        imgPosition,
+      };
+    },
+    render() {
+      const SsIcon = resolveComponent("ss-icon");
+      return h("div", { class: "ocr-img-box" }, [
+        h("div", { class: "img-bar" }, [
+          h("div", this.imageObj.name),
+          h("div", { class: "action-bar" }, [
+            h("div", { class: "ocr-img-range-box" }, [
+              h("input", {
+                type: "range",
+                min: 0,
+                max: 100,
+                value: this.zoom * 50, // 初始位置为50
+                onInput: this.handleRangeChange,
+              }),
+              h("span", { class: "line" }),
+            ]),
+            h(SsIcon, {
+              name: "reset",
+              size: "26px",
+              onClick: this.resetZoom,
+            }),
+          ]),
+        ]),
+        h("div", { class: "img-viewer", ref: "container" }, [
+          h(
+              "div",
+              {
+                class: "img-box",
+                style: {
+                  width: `${this.containerWidth}px`,
+                  height: `${this.containerHeight}px`,
+                  overflow: "hidden",
+                  position: "relative",
+                },
+              },
+              [
+                h("img", {
+                  src: this.imageObj.thumb,
+                  style: this.imgStyle,
+                  class: "zoomable-img",
+                  onMousedown: this.onMouseDown,
+                }),
+              ]
+          ),
+        ]),
+      ]);
+    },
+  };
+  // 搜索输入框组件
+  const SsSearchInput = {
+    name: "SsSearchInput",
+    props: {
+      name: String,
+      placeholder: String,
+      width: {
+        type: String,
+        default: "100px",
+      },
+      modelValue: String,
+    },
+    emits: ["update:modelValue", "search"],
+    setup(props, { emit }) {
+      const handleInput = (e) => {
+        emit("update:modelValue", e.target.value);
+      };
+      const handleKeyup = (e) => {
+        if (e.key === "Enter") {
+          emit("search");
+        }
+      };
+
+      return { handleInput, handleKeyup };
+    },
+    render() {
+      return h(
+          "div",
+          {
+            class: "input",
+            style: this.width ? { width: this.width } : undefined,
+          },
+          [
+            h("input", {
+              name: this.name,
+              placeholder: this.placeholder,
+              value: this.modelValue,
+              onInput: this.handleInput,
+              onKeyup: this.handleKeyup,
+            }),
+          ]
+      );
+    },
+  };
+  // ss-search-date-picker 日期时间选择器组件
+  const SsSearchDatePicker = {
+    name: "SsSearchDatePicker",
+    props: {
+      modelValue: {
+        type: [String, Number, Date],
+        default: "",
+      },
+      name: {
+        type: String,
+        required: true,
+      },
+      type: {
+        type: String,
+        default: "date",
+        validator: (value) => ["date", "datetime", "time"].includes(value),
+      },
+      fmt: {
+        type: String,
+        default: null,
+      },
+      placeholder: {
+        type: String,
+        default: "",
+      },
+      width: {
+        type: String,
+        default: "100%",
+      },
+    },
+
+    emits: ["update:modelValue"],
+
+    setup(props, { emit }) {
+      const errMsg = ref("");
+      const validate = () => {
+        if (window.ssVm) {
+          const result = window.ssVm.validateField(props.name);
+          console.log("validate", window.ssVm.validateField(props.name));
+          errMsg.value = result.valid ? "" : result.message;
+        }
+      };
+      // 根据type确定默认格式
+      const defaultFormat = computed(() => {
+        switch (props.type) {
+          case "datetime":
+            return "YYYY-MM-DD HH:mm:ss";
+          case "date":
+            return "YYYY-MM-DD";
+          case "time":
+            return "HH:mm:ss";
+        }
+      });
+
+      const convertJavaFormatToElement = (javaFormat) => {
+        if (!javaFormat) return null;
+        return javaFormat
+            .replace("yyyy", "YYYY")
+            .replace("MM", "MM")
+            .replace("dd", "DD")
+            .replace("HH", "HH")
+            .replace("mm", "mm")
+            .replace("ss", "ss");
+      };
+
+      const finalFormat = computed(() => {
+        if (props.fmt) {
+          return convertJavaFormatToElement(props.fmt);
+        }
+        return defaultFormat.value;
+      });
+
+      // 使用 resolveComponent 获取组件
+      const ElDatePicker = resolveComponent("ElDatePicker");
+      const ElTimePicker = resolveComponent("ElTimePicker");
+      const SsFormIcon = resolveComponent("SsFormIcon");
+      const ElIcon = resolveComponent("ElIcon");
+      let useTimePicker = true;
+      //"yyyy-MM-dd HH:mm:ss";  "日期字符串格式在java的写法",传到本组件fmt属性也是按这个格式
+      if (props.fmt) {
+        //有fmt属性,则以fmt属性优先判断类型
+        if (/[dMy]/.test(props.fmt)) {
+          //如果有传入日期格式,且含年月日
+          useTimePicker = false;
+        } else {
+          useTimePicker = true;
+        }
+      } else if (props.type !== "time") {
+        useTimePicker = false;
+      }
+      const dateType = computed(() => {
+        const fmt = props.fmt || "";
+        if (fmt.includes("HH:mm:ss")) {
+          return "datetime";
+        } else if (fmt.includes("HH:mm")) {
+          return "datetime";
+        } else if (fmt.includes("mm:ss")) {
+          return "time";
+        }
+        return "date";
+      });
+      const handleValueUpdate = (val) => {
+        emit("update:modelValue", val);
+        emit("change", val); // 同时触发 change 事件
+        setTimeout(() => {
+          validate();
+        }, 50);
+      };
+      return () =>
+          h(
+              "div",
+              { class: "ss-search-date-picker", style: { width: props.width } },
+              [
+                h("input", {
+                  type: "hidden",
+                  name: props.name,
+                  value: props.modelValue,
+                }),
+                h(useTimePicker ? ElTimePicker : ElDatePicker, {
+                  modelValue: props.modelValue,
+                  "onUpdate:modelValue": handleValueUpdate,
+                  type: dateType.value,
+                  format: finalFormat.value,
+                  "value-format": finalFormat.value,
+                  clearable: true,
+                  placeholder: props.placeholder,
+                  class: "custom-date-picker", // 用于自定义样式
+                  "time-arrow-control": props.type === "datetime", // 修改这里
+                  size: "large", // 添加这一行,改为 large 尺寸
+                  style: { width: "100%" },
+                  "prefix-icon": h(SsFormIcon, { class: "form-icon-time" }),
+                }),
+              ]
+          );
+    },
+  };
+  // 搜索按钮组件(包含下拉按钮)
+  const SsSearchButton = {
+    name: "SsSearchButton",
+    props: {
+      text: {
+        type: String,
+        required: true,
+      },
+      iconClass: {
+        type: String,
+        required: true,
+      },
+      opt: {
+        type: Array,
+        default: () => [],
+      },
+      checkId: {
+        type: String,
+        default: "0",
+      },
+    },
+    setup(props, { emit }) {
+      const currentId = ref(props.checkId || "0");
+      const showPopup = ref(false);
+
+      const handleMouseEnter = () => {
+        showPopup.value = true;
+      };
+
+      const handleMouseLeave = () => {
+        showPopup.value = false;
+      };
+
+      // 添加点击事件处理,阻止默认行为
+      const handleClick = (e) => {
+        e.preventDefault();
+        if (props.opt?.length > 0) {
+          const selectedOption =
+              currentId.value === "0"
+                  ? props.opt[0]
+                  : props.opt.find((opt) => opt.id === currentId.value);
+
+          if (selectedOption) {
+            selectedOption.callback?.();
+          }
+        } else {
+          emit("click", e);
+        }
+      };
+      // 获取显示文本
+      const getDisplayText = () => {
+        if (!props.opt?.length) return props.text;
+
+        const selectedOption =
+            currentId.value === "0"
+                ? props.opt[0]
+                : props.opt.find((opt) => opt.id === currentId.value);
+
+        return selectedOption ? selectedOption.desc : props.opt[0].desc;
+      };
+
+      return () =>
+          h(
+              "button",
+              {
+                class:
+                    props.opt?.length > 0
+                        ? "ss-drop-button ss-drop-button-more"
+                        : "ss-drop-button",
+                type: "button", // 明确指定按钮类型为 button
+                onMouseenter: handleMouseEnter,
+                onMouseleave: handleMouseLeave,
+                onClick: handleClick, // 添加点击事件处理
+              },
+              [
+                props.iconClass
+                    ? h("span", {
+                      class: props.iconClass,
+                      style: { fontFamily: "iconfont", marginRight: "5px" },
+                    })
+                    : null,
+                h("span", getDisplayText()),
+                props.opt.length > 0 &&
+                showPopup.value &&
+                h(
+                    "div",
+                    {
+                      class: "popup",
+                    },
+                    props.opt.map((item) =>
+                        h(
+                            "div",
+                            {
+                              onClick: (e) => {
+                                e.preventDefault(); // 选项点击也阻止默认行为
+                                e.stopPropagation(); // 阻止事件冒泡
+                                currentId.value = item.id; // 更新当前选中的ID
+                                item.callback();
+                                showPopup.value = false; // 选择后关闭弹窗
+                              },
+                            },
+                            item.desc
+                        )
+                    )
+                ),
+              ]
+          );
+    },
+  };
+  // 下拉按钮组件
+  const SsDropButton = {
+    name: "SsDropButton",
+    props: {
+      text: {
+        type: String,
+        required: true,
+      },
+      iconClass: {
+        type: String,
+        required: true,
+      },
+      opt: {
+        type: Array,
+        default: () => [],
+      },
+      checkId: {
+        type: String,
+        default: "0",
+      },
+      onclick: {
+        type: Function,
+        default: null,
+      },
+    },
+    setup(props) {
+      const currentId = ref(props.checkId || "0");
+      const showPopup = ref(false);
+
+      const handleMouseEnter = () => {
+        showPopup.value = true;
+      };
+
+      const handleMouseLeave = () => {
+        showPopup.value = false;
+      };
+
+      // 添加点击事件处理,阻止默认行为
+      const handleClick = (e) => {
+        e.preventDefault();
+        if (props.opt?.length > 0) {
+          const selectedOption =
+              currentId.value === "0"
+                  ? props.opt[0]
+                  : props.opt.find((opt) => opt.id === currentId.value);
+
+          if (selectedOption) {
+            selectedOption.callback?.();
+          }
+        } else if (props.onclick) {
+          props.onclick();
+        }
+      };
+      // 获取显示文本
+      const getDisplayText = () => {
+        if (!props.opt?.length) return props.text;
+
+        const selectedOption =
+            currentId.value === "0"
+                ? props.opt[0]
+                : props.opt.find((opt) => opt.id === currentId.value);
+
+        return selectedOption ? selectedOption.desc : props.opt[0].desc;
+      };
+
+      return () =>
+          h(
+              "button",
+              {
+                class:
+                    props.opt?.length > 0
+                        ? "ss-drop-button ss-drop-button-more"
+                        : "ss-drop-button",
+                type: "button", // 明确指定按钮类型为 button
+                onMouseenter: handleMouseEnter,
+                onMouseleave: handleMouseLeave,
+                onClick: handleClick, // 添加点击事件处理
+              },
+              [
+                h("span", {
+                  class: props.iconClass,
+                  style: { fontFamily: "iconfont" },
+                }),
+                h("span", getDisplayText()),
+                props.opt.length > 0 &&
+                showPopup.value &&
+                h(
+                    "div",
+                    {
+                      class: "popup",
+                    },
+                    props.opt.map((item) =>
+                        h(
+                            "div",
+                            {
+                              onClick: (e) => {
+                                e.preventDefault(); // 选项点击也阻止默认行为
+                                e.stopPropagation(); // 阻止事件冒泡
+                                currentId.value = item.id; // 更新当前选中的ID
+                                item.callback();
+                                showPopup.value = false; // 选择后关闭弹窗
+                              },
+                            },
+                            item.desc
+                        )
+                    )
+                ),
+              ]
+          );
+    },
+  };
+  /**
+   * 二级页面标签组件
+   * @name ss-sub-tab
+   * @description 用于展示二级页面的布局组件,包含左侧垂直标签导航(支持分组)和右侧iframe内容区
+   * @property {String} headerImage - 左侧顶部图片地址
+   * @property {Array} menuList - 菜单配置列表
+   * @property {Object} [activeMenu] - 当前选中的菜单项,不传则自动选择第一个可选菜单
+   * @property {Array} footerButtons - 底部按钮配置列表
+
+   */
+  const SsSubTab = {
+    name: "SsSubTab",
+    props: {
+      headerImage: {
+        type: String,
+        default: "",
+      },
+      menuList: {
+        type: Array,
+        required: true,
+      },
+      activeMenu: {
+        // 只需要传入标题
+        type: String,
+        default: "",
+      },
+      footerButtons: {
+        type: Array,
+        default: () => [],
+      },
+      leftDisplay: {
+        type: Boolean,
+        default: true,
+      },
+    },
+    emits: ["menu-change", "footer-click"],
+    setup(props, { emit }) {
+      // 根据标题找到对应的菜单项
+      const findMenuByTitle = (title) => {
+        for (const item of props.menuList) {
+          if (item.children?.length > 0) {
+            const child = item.children.find((c) => c.title === title);
+            if (child) return child;
+          } else if (item.title === title) {
+            return item;
+          }
+        }
+        return null;
+      };
+
+      // 计算默认选中的菜单项
+      const defaultActiveMenu = computed(() => {
+        if (props.activeMenu) {
+          const menu = findMenuByTitle(props.activeMenu);
+          if (menu) return menu;
+        }
+
+        const firstItem = props.menuList[0];
+        if (!firstItem) return null;
+
+        return firstItem.children?.length > 0
+            ? firstItem.children[0]
+            : firstItem;
+      });
+
+      const currentMenu = ref(defaultActiveMenu.value);
+
+      // 监听外部activeMenu变化
+      watch(
+          () => props.activeMenu,
+          (newTitle) => {
+            if (newTitle) {
+              const menu = findMenuByTitle(newTitle);
+              if (menu) {
+                currentMenu.value = menu;
+              }
+            }
+          }
+      );
+
+      // 选择菜单项时触发 menu-change 钩子
+      const selectItem = (item) => {
+        currentMenu.value = item;
+        emit("menu-change", item);
+      };
+
+      // 处理底部按钮点击
+      const handleFooterClick = (button, index) => {
+        emit("footer-click", { button, index });
+      };
+
+      return {
+        currentMenu,
+        selectItem,
+        handleFooterClick,
+      };
+    },
+    template: `
+          <div class="project-edit-container">
+              <div class="left-side" v-if="leftDisplay">
+              
+                  <!-- 头部图片 -->
+                  <div v-if="headerImage" class="menu-header">
+                      <div class="thumb">
+                          <img :src="headerImage" style="object-fit: cover;width: 100%;height: 100%;" />
+                      </div>
+                  </div>
+
+                  <!-- 菜单内容 -->
+                  <div class="menu-content">
+                      <div class="scroll-view">
+                          <template v-for="(menuItem, i) in menuList" :key="i">
+                              <!-- 分组菜单 -->
+                              <div v-if="menuItem.children?.length > 0" class="group">
+                                  <div class="menu-item" @click="menuItem.open = !menuItem.open">
+                                      <span>{{ menuItem.title }}</span>
+                                      
+                                      <span class="arrow">
+                                          <ss-icon :name="menuItem.open ? 'arrow-up' : 'arrow-down'" size="20px" />
+                                      </span>
+                                  </div>
+                                  <div v-show="menuItem.open" class="group-detail">
+                                      <div v-for="(item, j) in menuItem.children" 
+                                          :key="j" 
+                                          class="menu-item"
+                                          :class="{ active: item.name === currentMenu?.name }"
+                                          @click="selectItem(item)"
+                                      >
+                                          {{ item.title }}
+                                           
+                                           &nbsp;
+                                          <span class="menu-item-point" v-if="item.cgxList || item.objectList"></span>
+                                      </div>
+                                  </div>
+                              </div>
+                              <!-- 普通菜单项 -->
+                              <div v-else 
+                                  class="menu-item"
+                                  :class="{ active: menuItem.name === currentMenu?.name }"
+                                  @click="selectItem(menuItem)"
+                              >
+                                    {{ menuItem.title }}
+                                   &nbsp;
+                                  <span class="menu-item-point" v-if="menuItem.cgxList || menuItem.objectList"></span>
+                              </div>
+                          </template>
+                      </div>
+                  </div>
+                  
+                  <!-- 底部按钮 -->
+                  <div v-if="footerButtons.length > 0" 
+                      class="sub-tab-menu-footer"
+                      @click="footerButtons[0].onclick"
+                  >
+                      <div>{{ footerButtons[0].text }}</div>
+                      <ss-icon 
+                          v-if="footerButtons.length > 1" 
+                          name="arrow-up" 
+                          size="24px" 
+                      />
+                      
+                      <!-- 悬浮按钮 -->
+                      <div v-if="footerButtons.length > 1" class="sub-tab-menu-popup">
+                          <div v-for="(button, index) in footerButtons.slice(1)" 
+                              :key="index"
+                              @click.stop="button.onclick"
+                          >
+                              {{ button.text }}
+                          </div>
+                      </div>
+                  </div>
+                  
+              </div>
+
+              <!-- 右侧内容区域 -->
+              <div class="content-area fit-height-content" style="overflow: hidden;" :style="!leftDisplay ? { width: '100%' } : {}">
+                 
+                  <template v-for="(menuItem, i) in menuList" :key="i">
+                      <iframe 
+                          :src="menuItem.url"
+                          style="height: 100%;width: 100%;"
+                          frameborder="0"
+                          class="sub-tab-iframe"
+                          :id="i === 0 ? 'sub-tab-iframe' : ''"
+                          v-show="currentMenu?.name === menuItem.name"
+                      />
+                  </template>
+              </div>
+          </div>
+      `,
+  };
+  // <iframe
+  //     v-if="currentMenu?.url"
+  //     :src="currentMenu.url"
+  //     style="height: 100%;width: 100%;"
+  //     frameborder="0"
+  //     id="sub-tab-iframe"
+  // />
+
+  // ss-photo-upload 通用图片上传组件
+  const SsImgUpload = {
+    name: "SsImgUpload",
+    props: {
+      name: {
+        type: String,
+        required: true,
+      },
+      // 图片URL,用于回显
+      // url: {
+      //   type: String,
+      //   default: "",
+      // },
+      // 样式类名
+      class: {
+        type: String,
+        required: true,
+      },
+      // 裁剪配置
+      cropperOpt: {
+        type: Object,
+        default: () => ({
+          width: 360,
+          height: 360,
+          aspectRatio: 1,
+        }),
+      },
+      //上传图片url(未加图片名参数之前的部分)
+      ulUrl: {
+        type: String,
+        required: true,
+      },
+      //下载图片url(未加图片名参数之前的部分)
+      dlUrl: {
+        type: String,
+        required: true,
+      },
+      modelValue: [String, Number],
+    },
+
+    emits: ["update:modelValue"],
+
+    setup(props, { emit }) {
+      const inputId = Vue.computed(
+          () => `file_${Vue.getCurrentInstance().uid}`
+      );
+      //修改图片初始显示路径
+      let pathVal = ref(props.modelValue);
+      let picUrl = ref("");
+      if (props.modelValue) {
+        picUrl.value = props.dlUrl + "&path=" + props.modelValue;
+      }
+
+      Vue.onMounted(() => {
+        window.SS.cropper.init({
+          el: $(`#${inputId.value}`),
+          photoSize: {
+            width: props.cropperOpt.width,
+            height: props.cropperOpt.height,
+          },
+          aspectRatio: props.cropperOpt.aspectRatio,
+          uploadUrl: props.ulUrl,
+          success: (path) => {
+            pathVal.value = path;
+            picUrl.value = props.dlUrl + "&path=" + path;
+            emit("update:modelValue", path);
+          },
+        });
+      });
+
+      return () =>
+          h("div", { class: [props.class] }, [
+            h("input", {
+              type: "file",
+              accept: "image/*",
+              id: inputId.value,
+              style: { display: "none" },
+            }),
+            h("input", {
+              type: "hidden",
+              name: props.name,
+              value: pathVal.value,
+            }),
+            h(
+                "div",
+                {
+                  style: {
+                    width: "100%",
+                    height: "100%",
+                  },
+                  onClick: () => $(`#${inputId.value}`).click(),
+                },
+                [
+                  picUrl.value &&
+                  h("img", {
+                    src: picUrl.value,
+                    style:
+                        "width: 100%; height: 100%;object-fit: inherit;position: relative;z-index: 11;",
+                  }),
+                ]
+            ),
+          ]);
+    },
+  };
+
+  // 初始化函数,负责创建和挂载 Vue 应用
+  // window.SS = { dom: {} };
+  /**
+   * 获取当前窗口的父窗口
+   * @returns {Window} 父窗口对象
+   */
+  window.SS.topWin = (function (p, c) {
+    while (p != c) {
+      c = p;
+      p = p.parent;
+    }
+    return c;
+  })(window.parent, window);
+
+  window.SS.createSsDialogInstance = createSsDialogInstance;
+  /**
+   * 创建弹窗
+   * @param {Object} setting
+   * @param {Function} callbackEvent
+   */
+  window.SS.openDialog = function (setting, callbackEvent) {
+    if (setting.params) {
+      const encodedParams = encodeURIComponent(JSON.stringify(setting.params));
+      setting.src +=
+          (setting.src.includes("?") ? "&" : "?") + "params=" + encodedParams;
+    }
+
+    if (window.parent && window.parent !== window) {
+      window.parent.SS.createSsDialogInstance(setting, callbackEvent);
+    } else {
+      createSsDialogInstance(setting, callbackEvent);
+    }
+  };
+  //关闭弹窗
+  window.SS.closeDialog = function () {
+    console.log("关闭弹窗");
+    if (topWindow.dialogInstances.length > 0) {
+      const instance = topWindow.dialogInstances.pop();
+      console.log("instance", instance);
+      console.log("instance.callbackEvent", instance.callbackEvent);
+      console.log(
+          "instance.callbackEvent.end",
+          typeof instance.callbackEvent === "function"
+      );
+      if (instance.callbackEvent) {
+        // 判断是否有end回调并执行
+        if (typeof instance.callbackEvent === "function") {
+          instance.callbackEvent();
+        }
+        if (typeof instance.callbackEvent.end === "function") {
+          instance.callbackEvent.end();
+        }
+      }
+      instance.app.unmount(); // 卸载最后一个实例
+      if (instance.container && instance.container.parentNode) {
+        instance.container.parentNode.removeChild(instance.container); // 移除容器
+      }
+    }
+  };
+
+  /**
+   * 裁剪插件
+   */
+  window.SS.cropper = {
+    init: function (setting) {
+      if (!window.top.SS) window.top.SS = {};
+      // 重要:确保 cropper 对象的完整初始化
+      if (!window.top.SS.cropper) {
+        window.top.SS.cropper = {
+          settings: new Map(),
+          _backupSettings: {},
+          getSetting: this.getSetting,
+          clearSetting: this.clearSetting,
+          debug: this.debug,
+        };
+      } else if (!window.top.SS.cropper.settings) {
+        // 如果 cropper 存在但 settings 不存在,重新初始化 settings
+        window.top.SS.cropper.settings = new Map();
+        window.top.SS.cropper._backupSettings = {};
+      }
+      const uploaderId = `uploader_${Date.now()}_${Math.random()
+          .toString(36)
+          .substr(2, 9)}`;
+
+      window.top.SS.cropper.settings.set(uploaderId, setting);
+      window.top.SS.cropper._backupSettings[uploaderId] = setting;
+
+      setting.box = setting.box || "1";
+      var winSetting = {
+        headerTitle: "图片裁剪",
+        src: "/newUI/page/cropper.jsp",
+        width: "900",
+        height: "500",
+      };
+
+      $(setting.el).change(function () {
+        if (!window.SS.cropper.verify(setting)) {
+          $(setting.el).val(""); // 清空文件选择
+          return false;
+        }
+        var files = this.files;
+        if (files && files.length) {
+          if (!window.SS.cropper.verifySize($(setting.el)[0], 5)) {
+            $(setting.el).val(""); // 清空文件选择
+            alert("文件大小不能超过5M,请重新选择");
+            return false;
+          }
+          var URL = window.URL || window.webkitURL;
+          var file = files[0];
+          setting.file = file;
+
+          if (
+              /^image\/\w+$/.test(file.type) &&
+              /\.(jpg|jpeg|png|)$/i.test(file.name)
+          ) {
+            var uploadedImageURL = URL.createObjectURL(file);
+            setting.data = uploadedImageURL;
+            setting.fileName = file.name;
+            // console.log()
+            winSetting.params = {
+              ...setting,
+              uploaderId,
+            };
+            console.log("ss-componets中change之后的winSetting", winSetting);
+            SS.openDialog(winSetting, {
+              success: function (win) {
+                console.log("裁剪插件成功");
+                // win.cropperSetting = setting;
+              },
+              end: function () {
+                console.log("裁剪插件结束");
+                $(setting.el).val(""); // 清空文件选择
+              },
+            });
+          } else {
+            alert("请选择图片文件,支持jpg、jpeg、png格式");
+          }
+        }
+      });
+      return uploaderId;
+    },
+    verify: function (setting) {
+      if (!setting) {
+        console.error(" cropper setting is not undefined! ");
+        return false;
+      }
+      if (!setting.el) {
+        console.error(" cropper setting.el is not undefined! ");
+        return false;
+      }
+      if (setting.photoSize) {
+        if (
+            (!setting.photoSize.width && setting.photoSize.height) ||
+            (!setting.photoSize.height && setting.photoSize.width)
+        ) {
+          console.error(
+              " cropper setting.photoSize { width, height } is not undefined! "
+          );
+          return false;
+        }
+      }
+      if (!setting.box) {
+        setting.box = "1";
+      }
+
+      if (!setting.aspectRatio) {
+        setting.aspectRatio = 1 / 1;
+      }
+
+      return true;
+    },
+    verifySize: function (fileEl, maxSize) {
+      // 判断是否为IE浏览器: /msie/i.test(navigator.userAgent) 为一个简单正则
+      var isIE = /msie/i.test(navigator.userAgent) && !window.opera;
+      var fileSize = 0;
+      if (isIE && !fileEl.files) {
+        // IE浏览器
+        var filePath = fileEl.value; // 获得上传文件的绝对路径
+        var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
+        var file = fileSystem.GetFile(filePath);
+        fileSize = file.Size; // 文件大小,单位:b
+      } else {
+        // 非IE浏览器
+        fileSize = fileEl.files[0].size;
+      }
+
+      var size = fileSize / 1024 / 1024;
+      return !(size > maxSize);
+    },
+    // 获取特定上传组件的setting
+    getSetting: function (uploaderId) {
+      if (!window.top.SS?.cropper) {
+        console.warn("顶层窗口中未找到 SS.cropper");
+        return null;
+      }
+
+      // 优先从 Map 中获取
+      let setting = window.top.SS.cropper.settings.get(uploaderId);
+
+      // 如果 Map 中没有,尝试从备份中获取
+      if (!setting && window.top.SS.cropper._backupSettings[uploaderId]) {
+        console.log("从备份中恢复 setting");
+        setting = window.top.SS.cropper._backupSettings[uploaderId];
+        // 恢复到 Map 中
+        window.top.SS.cropper.settings.set(uploaderId, setting);
+      }
+
+      return setting;
+    },
+
+    // 清理特定上传组件的setting
+    clearSetting: function (uploaderId) {
+      if (!window.top.SS?.cropper) return;
+
+      window.top.SS.cropper.settings.delete(uploaderId);
+      delete window.top.SS.cropper._backupSettings[uploaderId];
+      console.log(
+          "清理设置后的 Map size:",
+          window.top.SS.cropper.settings.size
+      );
+    },
+  };
+
+  /**
+   * 获取url中的参数
+   * @returns {Object}
+   */
+  window.SS.getQueryParams = function () {
+    const params = {};
+    const queryString = window.location.search.substring(1);
+    const pairs = queryString.split("&");
+    for (let i = 0; i < pairs.length; i++) {
+      const pair = pairs[i].split("=");
+      params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
+    }
+    if (params.params) {
+      try {
+        params.params = JSON.parse(params.params);
+      } catch (e) {
+        console.error("Failed to parse params:", e);
+      }
+    }
+
+    return params;
+  };
+
+  /**
+   * 创建vue应用
+   * @param {Object} config 配置项
+   * @values {String} config.el 挂载的元素
+   * @values {Boolean} config.isDialogPage 是否是弹窗页面 决定了是否可以使用顶天立地
+   * @values {Object} config.vueOptions vue配置项
+   * @returns {Object} vue实例
+   */
+  window.SS.dom.initializeFormApp = function (config) {
+    const { el, isDialogPage = false, ...vueOptions } = config;
+    const app = createApp({
+      ...vueOptions,
+    });
+    // 如果是弹窗iframe里面的html的话 给当前的页面挂上事件 实现顶天立地的效果
+    if (isDialogPage) {
+      function checkScroll() {
+        // 选出所有fit-height-content的元素 如果有滚动条
+        const elements = document.querySelectorAll(".fit-height-content");
+        let hasScrollBar = false;
+        // 检查元素是否有滚动条 检查当前窗口的所有元素
+        // 如果有滚动条,则将结果设置为true
+        elements.forEach((el) => {
+          if (el.scrollHeight > el.clientHeight) {
+            hasScrollBar = true;
+          }
+        });
+        // 将结果发送给父窗口
+        window.parent.postMessage({ hasScrollBar }, "*");
+      }
+
+      function addScrollListeners() {
+        const elements = document.querySelectorAll("div");
+        elements.forEach((el) => {
+          el.addEventListener("scroll", checkScroll);
+        });
+      }
+      const observer = new MutationObserver((mutations) => {
+        addScrollListeners();
+        checkScroll();
+      });
+
+      observer.observe(document.body, {
+        childList: true,
+        subtree: true,
+      });
+
+      window.addEventListener("resize", checkScroll);
+    }
+    // 注册组件
+    app.component("SsLoginIcon", SsLoginIcon);
+    app.component("SsMark", SsMark);
+    app.component("SsFullStyleHeader", SsFullStyleHeader);
+    app.component("SsDialog", SsDialog);
+    app.component("SsInput", SsInput);
+    app.component("SsObjp", SsObjp);
+    app.component("SsHidden", SsHidden);
+    app.component("SsCcp", SsCcp);
+    app.component("SsDatePicker", SsDatePicker);
+    app.component("SsIcon", SsIcon);
+    app.component("SsCommonIcon", SsCommonIcon);
+    app.component("SsBreadcrumb", SsBreadcrumb);
+    app.component("SsEditor", SsEditor);
+    app.component("SsDialogIcon", SsDialogIcon);
+    app.component("SsBottomButton", SsBottomButton);
+    app.component("SsNavIcon", SsNavIcon);
+    app.component("SsHeaderIcon", SsHeaderIcon);
+    app.component("SsGolbalMenuIcon", SsGolbalMenuIcon);
+    app.component("SsCartListIcon", SsCartListIcon);
+    app.component("SsQuickIcon", SsQuickIcon);
+    app.component("SsFormIcon", SsFormIcon);
+    app.component("SsBottomDivIcon", SsBottomDivIcon);
+    app.component("SsEditorIcon", SsEditorIcon);
+    app.component("SsValidate", SsValidate);
+    app.component("SsOnoffbutton", SsOnoffbutton);
+    app.component("SsOnoffbuttonArray", SsOnoffbuttonArray);
+    app.component("SsTextarea", SsTextarea);
+    app.component("SsLoginInput", SsLoginInput);
+    app.component("SsLoginButton", SsLoginButton);
+    app.component("SsSearch", SsSearch);
+    app.component("SsCartItem", SsCartItem);
+    app.component("SsCartItem2", SsCartItem2);
+    app.component("SsListCard", SsListCard);
+    app.component("SsFolderCard", SsFolderCard);
+    app.component("SsFolderCartView", SsFolderCartView);
+    app.component("SsPage", SsPage);
+    app.component("SsRightInfo", SSRightInfo);
+    app.component("SsSuccessPopup", SsSuccessPopup);
+    app.component("SsErrorDialog", SsErrorDialog);
+    app.component("SsVerify", SsVerify);
+    app.component("SsVerifyNode", SsVerifyNode);
+    app.component("SsOrcImgBox", SsOrcImgBox);
+    app.component("ss-search-input", SsSearchInput);
+    app.component("ss-search-date-picker", SsSearchDatePicker);
+
+    app.component("ss-search-button", SsSearchButton);
+    app.component("ss-drop-button", SsDropButton);
+    app.component("ss-sub-tab", SsSubTab);
+    app.component("ss-img", SsImgUpload);
+    // 设置为中文
+    app.use(ElementPlus, {
+      locale: ElementPlusLocaleZhCn,
+    });
+    // console.log(ElementPlus);
+    // 确保 ElementPlusIconsVue
+    // if (window.ElementPlusIconsVue) {
+    //   // 注册 Element Plus 图标组件
+    //   for (const [key, component] of Object.entries(
+    //     window.ElementPlusIconsVue
+    //   )) {
+    //     console.log(key, component);
+    //     app.component(key, component);
+    //   }
+    // }
+    // 挂载首页的组件
+    for (const componentName in IndexComponents) {
+      app.component(componentName, IndexComponents[componentName]);
+    }
+    // 挂载echarts的组件
+    for (const componentName in EchartComponents) {
+      app.component(componentName, EchartComponents[componentName]);
+    }
+    // 挂载 Vue 应用
+    const vm = app.mount(el);
+    vm.data = vueOptions.data();
+
+    return vm;
+  };
+})();

+ 2 - 0
api/bzrdm.js

@@ -0,0 +1,2 @@
+// 班主任点名api
+import request from "@/utils/request";

+ 1 - 0
api/xuncha.js

@@ -1,3 +1,4 @@
+//  巡查api
 import request from "@/utils/request";
 
 export const xunchaApi = {

+ 177 - 0
components/SsOnoffButton/index.vue

@@ -0,0 +1,177 @@
+<template>
+  <view class="ss-onoff-button" :class="{ checked: isChecked }" @click="toggleSelect">
+    <text class="button-label">{{ label }}</text>
+    <view class="button-mark">
+      <text
+        class="form-icon"
+        :class="isChecked ? 'form-icon-onoffbutton-checked' : 'form-icon-onoffbutton-unchecked'"
+      ></text>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { computed, inject, nextTick } from 'vue'
+
+const props = defineProps({
+  // 字段名称,用于表单校验
+  name: {
+    type: String,
+    required: true
+  },
+  // 显示标签
+  label: {
+    type: String,
+    required: true
+  },
+  // 按钮的值
+  value: {
+    type: [String, Number],
+    required: true
+  },
+  // 宽度设置
+  width: {
+    type: String,
+    default: ''
+  },
+  // v-model 绑定的值
+  modelValue: {
+    type: [String, Number, Array],
+    default: ''
+  },
+  // 是否多选模式
+  multiple: {
+    type: Boolean,
+    default: false
+  }
+})
+
+const emit = defineEmits(['update:modelValue', 'change'])
+
+// 从父组件注入校验相关功能
+const validateField = inject('validateField', () => {})
+
+// 解析 modelValue,支持逗号分隔的字符串和数组
+const parseModelValue = (val) => {
+  if (!val) return []
+  
+  // 如果是数组,直接返回字符串数组
+  if (Array.isArray(val)) {
+    return val.map(v => v.toString())
+  }
+  
+  // 如果是字符串,按逗号分割
+  const cleanValue = val.toString().replace(/^,+/, '') // 去掉开头的逗号
+  if (cleanValue.includes('|')) {
+    return cleanValue.split('|')
+  }
+  if (cleanValue.includes(',')) {
+    return cleanValue.split(',')
+  }
+  return cleanValue ? [cleanValue] : []
+}
+
+// 判断当前按钮是否选中
+const isChecked = computed(() => {
+  if (props.multiple) {
+    const currentValue = parseModelValue(props.modelValue)
+    return currentValue.includes(props.value.toString())
+  }
+  return props.modelValue === props.value
+})
+
+// 切换选中状态
+const toggleSelect = () => {
+  if (props.multiple) {
+    // 多选模式
+    const currentValue = parseModelValue(props.modelValue)
+    const index = currentValue.indexOf(props.value.toString())
+    let newValue
+    
+    if (index === -1) {
+      // 添加选项
+      newValue = [...currentValue, props.value.toString()]
+    } else {
+      // 移除选项
+      newValue = currentValue.filter(v => v !== props.value.toString())
+    }
+    
+    // 发送更新事件,使用逗号分隔的字符串格式
+    const emitValue = newValue.join(',')
+    emit('update:modelValue', emitValue)
+    emit('change', emitValue, newValue)
+  } else {
+    // 单选模式
+    emit('update:modelValue', props.value)
+    emit('change', props.value)
+  }
+  
+  // 触发校验
+  nextTick(() => {
+    if (props.name) {
+      validateField(props.name)
+    }
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+/* 引入iconfont样式 */
+@import '../../static/iconfont/iconfont.css';
+
+.ss-onoff-button {
+  position: relative;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  padding: 10rpx 36rpx;
+  border: 2rpx solid #BFC1C6;
+  border-radius: 4rpx;
+  background-color: #fff;
+  color: #C3C6CA;
+  font-size: 28rpx;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  // margin-right: 20rpx;
+  // margin-bottom: 20rpx;
+  // min-width: 120rpx;
+
+  &.checked {
+    color: #393D51;
+    border-color: #393D51;
+    // background-color: #F8F9FA;
+  }
+
+  .button-label {
+    flex: 1;
+    text-align: center;
+    line-height: 1.2;
+  }
+
+  .button-mark {
+    position: absolute;
+    bottom: 0rpx;
+    right: 0rpx;
+    width: 36rpx;
+    height: 36rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: inherit;
+  }
+}
+
+/* 表单组件icon样式 - 完全按照PC端实现 */
+.form-icon {
+  font-size: 36rpx;
+  font-family: "iconfont";
+}
+
+.form-icon-onoffbutton-checked::before {
+  content: "\e62d";
+}
+
+.form-icon-onoffbutton-unchecked::before {
+  content: "\e62b";
+}
+</style>

+ 2 - 2
components/SsSelect/index.vue

@@ -30,10 +30,10 @@
         v-for="(option, index) in optionsList"
         :key="index"
         class="option-item"
-        :class="{ selected: option[mapping.value] === selectedValue }"
+        :class="{ selected: option[props.mapping.value] === selectedValue }"
         @click.stop="selectOption(option)"
       >
-        {{ option[mapping.text] }}
+        {{ option[props.mapping.text] }}
       </view>
     </view>
     

+ 6 - 0
pages.json

@@ -27,6 +27,12 @@
 				"navigationBarTitleText": "校长巡查"
 			}
 		},
+		{
+			"path": "pages/kqjl/kqjl_bzrDm_list",
+			"style": {
+				"navigationBarTitleText": "班主任点名"
+			}
+		},
 		{
 			"path": "pages/kqjl/kqjl_bzrDm",
 			"style": {

+ 1 - 1
pages/index/index.vue

@@ -191,7 +191,7 @@ const goToMessage = () => {
 const goToBzrDm = () => {
 	if (checkLogin()) {
 		uni.navigateTo({
-			url: '/pages/kqjl/kqjl_bzrDm'
+			url: '/pages/kqjl/kqjl_bzrDm_list'
 		})
 	} else {
 		pleaseLogin()

+ 323 - 0
pages/kqjl/components/SeatLayout.vue

@@ -0,0 +1,323 @@
+<template>
+  <!--
+    座位布局组件
+    功能:管理学生座位的显示和交互
+    支持两种模式:
+    1. 全览模式:缩放显示所有座位,支持双击进入点名模式
+    2. 点名模式:正常尺寸显示,支持滚动和学生状态切换
+  -->
+  <view class="seat-layout-container">
+    <!-- 全览模式 (overview 和 overview-simple) -->
+    <view
+      v-if="mode !== 'attendance'"
+      class="seat-layout overview-mode"
+      :style="overviewContainerStyle"
+    >
+      <view class="overview-content" :style="layoutStyle" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
+        <!-- 学生卡片网格 -->
+        <view class="seat-grid" :style="gridStyle">
+          <StudentCard
+            v-for="student in students"
+            :key="student.id"
+            :student="student"
+            :attendance-mode="false"
+            :style="getCardPosition(student)"
+            @statusChange="handleStatusChange"
+            @click="handleCardClick"
+          />
+        </view>
+      </view>
+    </view>
+
+    <!-- 点名模式 -->
+    <scroll-view
+      v-else
+      ref="scrollViewRef"
+      class="seat-layout attendance-mode"
+      scroll-x="true"
+      scroll-y="true"
+      enable-flex="true"
+      :scroll-top="scrollTop"
+      :scroll-left="scrollLeft"
+      @touchstart="handleTouchStart"
+      @touchend="handleTouchEnd"
+    >
+      <!-- 学生卡片网格容器 -->
+      <view class="scroll-content" :style="scrollContentStyle">
+        <view class="seat-grid" :style="gridStyle">
+          <StudentCard
+            v-for="student in students"
+            :key="student.id"
+            :student="student"
+            :attendance-mode="true"
+            :style="getCardPosition(student)"
+            @statusChange="handleStatusChange"
+            @click="handleCardClick"
+          />
+        </view>
+      </view>
+    </scroll-view>
+  </view>
+</template>
+
+<script setup>
+/**
+ * 座位布局组件
+ *
+ * 主要功能:
+ * 1. 学生座位的网格布局显示
+ * 2. 全览模式和点名模式的切换
+ * 3. 座位布局的缩放和滚动控制
+ * 4. 双击事件处理和模式切换
+ * 5. 滚动位置重置和页面滚动控制
+ */
+
+import { ref, computed, watch, defineProps, defineEmits } from 'vue'
+import StudentCard from './StudentCard.vue'
+
+const props = defineProps({
+  students: {
+    type: Array,
+    default: () => []
+  },
+  layout: {
+    type: Object,
+    default: () => ({ rows: 20, cols: 10 })
+  },
+  mode: {
+    type: String,
+    default: 'overview' // 'overview' | 'attendance'
+  }
+})
+
+const emit = defineEmits(['modeChange', 'statusChange', 'studentClick'])
+
+// 触摸相关状态
+const lastTap = ref(0)
+const touchStartTime = ref(0)
+const touchStartPos = ref({ x: 0, y: 0 })
+
+// 滚动控制
+const scrollTop = ref(0)
+const scrollLeft = ref(0)
+const scrollViewRef = ref(null)
+
+// 卡片尺寸常量
+const CARD_WIDTH = 200 // rpx
+const CARD_HEIGHT = 280 // rpx - 根据新的卡片布局调整(20+224+20+文字+20+10)
+const CARD_GAP = 12 // rpx - 适中的间距,避免太挤或太松
+
+// 计算布局样式
+const layoutStyle = computed(() => {
+  const totalWidthRpx = props.layout.cols * (CARD_WIDTH + CARD_GAP) - CARD_GAP // rpx单位
+  const totalHeightRpx = props.layout.rows * (CARD_HEIGHT + CARD_GAP) - CARD_GAP // rpx单位
+
+  console.log('SeatLayout 计算样式:', {
+    mode: props.mode,
+    students: props.students.length,
+    layout: props.layout,
+    totalWidthRpx,
+    totalHeightRpx
+  })
+
+  if (props.mode === 'overview' || props.mode === 'overview-simple') {
+    // 全览模式:缩放到屏幕宽度的90%,留边距
+    const systemInfo = uni.getSystemInfoSync()
+    const screenWidthPx = systemInfo.windowWidth // px单位
+    const screenWidthRpx = screenWidthPx * 2 // 转换为rpx (1px = 2rpx)
+    const targetWidthRpx = screenWidthRpx * 0.9 // 使用90%宽度,留10%边距
+    const scale = targetWidthRpx / totalWidthRpx
+
+    return {
+      transform: `scale(${scale})`,
+      transformOrigin: 'top left',
+      width: `${totalWidthRpx}rpx`,
+      height: `${totalHeightRpx}rpx`
+    }
+  } else {
+    // 点名模式:正常尺寸,可滚动
+    return {
+      transform: 'scale(1)',
+      transformOrigin: 'top left',
+      width: `${totalWidthRpx}rpx`,
+      height: `${totalHeightRpx}rpx`
+    }
+  }
+})
+
+// 网格样式
+const gridStyle = computed(() => ({
+  display: 'grid',
+  gridTemplateColumns: `repeat(${props.layout.cols}, ${CARD_WIDTH}rpx)`,
+  gridTemplateRows: `repeat(${props.layout.rows}, auto)`, // 改为auto,让行高自适应卡片内容
+  gap: `${CARD_GAP}rpx`,
+  padding: `${CARD_GAP}rpx`
+}))
+
+// 全览模式容器样式
+const overviewContainerStyle = computed(() => ({
+  width: '100%',
+  minHeight: '600rpx', // 最小高度,允许内容撑开
+  overflow: 'visible', // 允许内容显示
+  position: 'relative'
+}))
+
+// 滚动内容样式
+const scrollContentStyle = computed(() => {
+  const totalWidthRpx = props.layout.cols * (CARD_WIDTH + CARD_GAP) + CARD_GAP
+  // 高度改为自适应,不再固定计算
+
+  return {
+    width: `${totalWidthRpx}rpx`,
+    minWidth: '100%',
+    minHeight: '100%'
+    // 移除固定高度,让内容自适应
+  }
+})
+
+// 获取卡片位置
+const getCardPosition = (student) => {
+  return {
+    gridColumn: student.col,
+    gridRow: student.row
+  }
+}
+
+// 处理触摸开始
+const handleTouchStart = (e) => {
+  touchStartTime.value = Date.now()
+  touchStartPos.value = {
+    x: e.touches[0].clientX,
+    y: e.touches[0].clientY
+  }
+}
+
+// 处理触摸结束
+const handleTouchEnd = () => {
+  const touchEndTime = Date.now()
+  const touchDuration = touchEndTime - touchStartTime.value
+  
+  // 检测双击
+  if (touchDuration < 300) { // 快速点击
+    const now = Date.now()
+    if (now - lastTap.value < 300) {
+      // 双击检测成功
+      handleDoubleClick()
+    }
+    lastTap.value = now
+  }
+}
+
+// 处理双击事件
+const handleDoubleClick = () => {
+  console.log('双击事件,当前模式:', props.mode)
+
+  if (props.mode === 'attendance') {
+    // 从点名模式退出
+    const newMode = 'overview'
+    console.log('从点名模式退出到:', newMode)
+    emit('modeChange', newMode)
+  } else {
+    // 从全览模式(overview 或 overview-simple)进入点名模式
+    const newMode = 'attendance'
+    console.log('进入点名模式:', newMode)
+    emit('modeChange', newMode)
+  }
+}
+
+// 处理学生状态变化
+const handleStatusChange = (statusData) => {
+  emit('statusChange', statusData)
+}
+
+// 处理卡片点击
+const handleCardClick = (student) => {
+  emit('studentClick', student)
+}
+
+// 监听模式变化,重置滚动位置
+watch(() => props.mode, (newMode, oldMode) => {
+  console.log('模式变化:', oldMode, '->', newMode)
+  if (oldMode === 'attendance' && (newMode === 'overview' || newMode === 'overview-simple')) {
+    console.log('从点名模式退出,重置页面滚动位置')
+
+    // 使用 uni.pageScrollTo 强制滚动到页面顶部
+    uni.pageScrollTo({
+      scrollTop: 0,
+      duration: 300,
+      success: () => {
+        console.log('页面滚动重置成功')
+      },
+      fail: (err) => {
+        console.log('页面滚动重置失败:', err)
+      }
+    })
+
+    // 同时重置 scroll-view 的滚动位置
+    scrollTop.value = 0
+    scrollLeft.value = 0
+
+    console.log('滚动位置重置完成')
+  }
+})
+</script>
+
+<style lang="scss" scoped>
+.seat-layout-container {
+  width: 100%;
+  min-height: 100%;
+  position: relative;
+  overflow: visible;
+  
+  .seat-layout {
+    transition: transform 0.3s ease;
+    
+    &.overview-mode {
+      // 全览模式样式
+      pointer-events: auto;
+
+      .overview-content {
+        width: 100%;
+        height: 100%;
+      }
+
+      .seat-grid {
+        pointer-events: none; // 禁用卡片交互
+      }
+    }
+    
+    &.attendance-mode {
+      // 点名模式样式
+      width: 100%;
+      height: 100%;
+
+      .scroll-content {
+        display: flex;
+        flex-direction: column;
+      }
+
+      .seat-grid {
+        pointer-events: auto; // 启用卡片交互
+        flex-shrink: 0;
+      }
+    }
+  }
+  
+  .seat-grid {
+    min-height: 100%;
+  }
+  
+  .mode-tip {
+    position: absolute;
+    bottom: 40rpx;
+    left: 50%;
+    transform: translateX(-50%);
+    background-color: rgba(0, 0, 0, 0.7);
+    color: white;
+    padding: 20rpx 40rpx;
+    border-radius: 40rpx;
+    font-size: 28rpx;
+    z-index: 100;
+  }
+}
+</style>

+ 284 - 0
pages/kqjl/components/StudentCard.vue

@@ -0,0 +1,284 @@
+<template>
+  <!--
+    学生卡片组件
+    功能:显示单个学生的信息和考勤状态
+    支持:
+    1. 学生基本信息显示(头像、姓名、编号)
+    2. 考勤状态可视化(出勤、旷课、迟到、早退、请假)
+    3. 点击切换考勤状态(仅在点名模式下)
+    4. 一寸证件照比例的头像显示
+  -->
+  <view
+    class="student-card"
+    @click="handleCardClick"
+  >
+    <!-- 学生头像 -->
+    <view class="avatar-container">
+      <image 
+        class="avatar" 
+        :src="student.avatar || '/static/images/default-avatar.png'" 
+        mode="aspectFill"
+        @error="handleImageError"
+      />
+    </view>
+    
+    <!-- 学生信息 -->
+    <view class="student-info">
+      <view class="student-code">{{ student.code }}</view>
+      <view class="student-name">{{ student.name }}</view>
+    </view>
+    
+    <!-- 底部状态指示线 -->
+    <view class="status-line-container">
+      <!-- 默认灰色底线 -->
+      <view class="status-line-base"></view>
+
+      <!-- 迟到:左半边红线 -->
+      <view v-if="student.status === 11" class="status-line-overlay status-late-overlay"></view>
+
+      <!-- 旷课:整条红线 -->
+      <view v-if="student.status === 1" class="status-line-overlay status-absent-overlay"></view>
+
+      <!-- 早退:右半边红线 -->
+      <view v-if="student.status === 21" class="status-line-overlay status-early-overlay"></view>
+    </view>
+
+    <!-- 临时:整个卡片可点击,用于测试 -->
+  </view>
+</template>
+
+<script setup>
+/**
+ * 学生卡片组件
+ *
+ * 主要功能:
+ * 1. 显示学生基本信息(头像、姓名、编号)
+ * 2. 考勤状态的可视化显示
+ * 3. 考勤状态的点击切换功能
+ * 4. 支持一寸证件照比例的头像显示
+ *
+ * 考勤状态说明(底部指示线):
+ * - 81: 出勤(灰色底线)
+ * - 1: 旷课(整条红线)
+ * - 11: 迟到(左半边红线)
+ * - 21: 早退(右半边红线)
+ * - 0: 请假(灰色底线)
+ */
+
+import { defineProps, defineEmits } from 'vue'
+
+const props = defineProps({
+  student: {
+    type: Object,
+    required: true,
+    default: () => ({
+      id: '',
+      name: '',
+      code: '',
+      avatar: '',
+      row: 1,
+      col: 1,
+      status: 81 // 81-出勤, 1-旷课, 11-迟到, 21-早退, 0-请假
+    })
+  },
+  // 是否在点名模式下(影响交互)
+  attendanceMode: {
+    type: Boolean,
+    default: false
+  }
+})
+
+const emit = defineEmits(['click', 'statusChange'])
+
+// 处理卡片点击
+const handleCardClick = () => {
+  console.log('点击了学生卡片:', props.student.name, '当前模式:', props.attendanceMode)
+  if (!props.attendanceMode) {
+    console.log('不在点名模式,忽略点击')
+    return // 只在点名模式下响应点击
+  }
+
+  console.log('开始状态切换,当前状态:', props.student.status)
+  
+  // 状态切换逻辑:81(出勤) → 1(旷课) → 11(迟到) → 21(早退) → 81(出勤)
+  let newStatus
+  switch (props.student.status) {
+    case 81: // 出勤 → 旷课
+      newStatus = 1
+      break
+    case 1: // 旷课 → 迟到
+      newStatus = 11
+      break
+    case 11: // 迟到 → 早退
+      newStatus = 21
+      break
+    case 21: // 早退 → 出勤
+      newStatus = 81
+      break
+    default: // 其他状态 → 出勤
+      newStatus = 81
+  }
+  
+  emit('statusChange', {
+    studentId: props.student.id,
+    oldStatus: props.student.status,
+    newStatus: newStatus
+  })
+  
+  emit('click', props.student)
+}
+
+// 处理头像加载失败
+const handleImageError = () => {
+  console.log('头像加载失败:', props.student.name)
+}
+</script>
+
+<style lang="scss" scoped>
+.student-card {
+  width: 200rpx;
+  background-color: #fff;
+  border: 2rpx solid #E5E5E5;
+  border-radius: 8rpx;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  position: relative;
+  overflow: hidden;
+  transition: all 0.3s ease;
+  padding: 20rpx 20rpx 0 20rpx; // 上右下左,底部不加padding因为有状态线
+  box-sizing: border-box;
+  // 头像容器 - 一寸证件照比例 (2.5:3.5 ≈ 5:7)
+  .avatar-container {
+    width: 100%;  // 占满容器宽度
+    height: 224rpx; // 按一寸证件照比例 (160 * 1.4 = 224)
+    margin-top: 0;
+    border-radius: 8rpx;
+    overflow: hidden;
+
+    .avatar {
+      width: 100%;
+      height: 100%;
+      background-color: #F5F5F5;
+    }
+  }
+  
+  // 学生信息
+  .student-info {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: 20rpx;
+    margin-bottom: 20rpx; // 添加底部边距,为状态线留出空间
+    
+    .student-code {
+      font-size: 24rpx;
+      color: #666;
+      text-align: left;
+    }
+    
+    .student-name {
+      font-size: 28rpx;
+      color: #333;
+      font-weight: bold;
+      text-align: right;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+  }
+  
+  // 底部状态指示线样式
+  .status-line-container {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 10rpx;
+    pointer-events: none;
+  }
+
+  // 默认灰色底线
+  .status-line-base {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 10rpx;
+    background-color: #e0e0e0;
+    border-radius: 8rpx;
+  }
+
+  // 状态指示线覆盖层
+  .status-line-overlay {
+    position: absolute;
+    bottom: 0;
+    height: 10rpx;
+    background-color: #ff4444;
+    border-radius: 8rpx;
+  }
+
+  // 迟到:左半边红线
+  .status-late-overlay {
+    left: 0;
+    width: 50%;
+  }
+
+  // 旷课:整条红线
+  .status-absent-overlay {
+    left: 0;
+    width: 100%;
+  }
+
+  // 早退:右半边红线
+  .status-early-overlay {
+    right: 0;
+    width: 50%;
+  }
+  
+  // 底部点击条
+  .click-bar {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    width: 100%;
+    height: 40rpx; // 增加高度,更容易点击
+    background-color: rgba(0, 0, 0, 0.05); // 淡灰色背景
+    cursor: pointer;
+    z-index: 10;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .click-hint {
+      font-size: 20rpx;
+      color: #999;
+      opacity: 0.7;
+    }
+
+    // 点击时的反馈效果
+    &:active {
+      background-color: rgba(0, 0, 0, 0.1);
+    }
+  }
+
+  // 状态样式
+  &.status-normal {
+    opacity: 1;
+  }
+
+  &.status-late {
+    opacity: 1;
+  }
+
+  &.status-early {
+    opacity: 1;
+  }
+
+  &.status-absent {
+    opacity: 1;
+  }
+}
+</style>

+ 563 - 3
pages/kqjl/kqjl_bzrDm.vue

@@ -1,12 +1,572 @@
 <template>
-    <!-- 班主任点名 -->
-    班主任点名
+    <!--
+        班主任点名页面
+        功能:支持班级考勤管理,包括学生状态切换、座位布局显示等
+        模式:
+        - overview: 初始完整筛选条件模式
+        - overview-simple: 双击退出后的简化模式
+        - attendance: 点名模式
+    -->
+    <view class="page-container"
+          @touchstart="handlePageTouchStart"
+          @touchmove="handlePageTouchMove"
+          @touchend="handlePageTouchEnd">
+
+        <!-- 筛选条件区域 -->
+        <view class="filter-area" :class="{ 'simple-mode': attendanceMode !== 'overview' }">
+            <!-- 完整模式:显示表单 -->
+            <Form v-if="attendanceMode === 'overview'" :rules="fieldConfigs" v-model="formData" ref="formRef">
+            <up-table>
+                <up-tr>
+                    <up-th>班级</up-th>
+                    <Td field="bj">
+                        <SsSelect
+                            v-model="formData.bj"
+                            :options="bjOption"
+                            :loading="bjLoading"
+                            placeholder="请选择班级"
+                            @change="onXcTypeChange"
+                        />
+                    </Td>
+                </up-tr>
+                <up-tr>
+                    <up-th>日期</up-th>
+                    <Td field="rq">
+                        <SsInput v-model="formData.rq" placeholder="请输入日期" />
+                    </Td>
+                </up-tr>
+                <up-tr>
+                    <up-th>节次</up-th>
+                    <Td field="jc">
+                        <view class="onoff-button-group">
+                            <SsOnoffButton
+                                v-model="formData.jc"
+                                name="jc"
+                                label="上午"
+                                value="1"
+                            />
+                            <SsOnoffButton
+                                v-model="formData.jc"
+                                name="jc"
+                                label="下午"
+                                value="2"
+                            />
+                            <SsOnoffButton
+                                v-model="formData.jc"
+                                name="jc"
+                                label="晚上"
+                                value="3"
+                            />
+                        </view>
+                    </Td>
+                </up-tr>
+            </up-table>
+            </Form>
+
+            <!-- 简化模式:显示回显信息 -->
+            <view v-else class="simple-display">
+                <text class="display-text">{{ displayText }}</text>
+            </view>
+        </view>
+
+        <!-- 点名区域 -->
+        <view class="attendance-area">
+        <SeatLayout
+            :students="studentList"
+            :layout="seatLayout"
+            :mode="attendanceMode"
+            @modeChange="handleModeChange"
+            @statusChange="handleStatusChange"
+            @studentClick="handleStudentClick"
+        />
+        </view>
+
+        <!-- 下拉提示 -->
+        <view v-if="attendanceMode === 'overview-simple'" class="pull-indicator" :class="{ 'show': showPullIndicator }">
+            <text class="pull-text">下拉恢复筛选条件</text>
+        </view>
+
+        <!-- 底部按钮 - 只在非点名模式下显示 -->
+        <SsBottom
+            v-if="attendanceMode !== 'attendance'"
+            :buttons="bottomButtons"
+            @button-click="handleBottomAction"
+        />
+    </view>
 </template>
 
 <script setup>
+/**
+ * 班主任点名页面
+ *
+ * 主要功能:
+ * 1. 筛选条件管理(班级、日期、节次)
+ * 2. 学生座位布局显示和缩放
+ * 3. 点名模式切换(全览 ↔ 点名)
+ * 4. 学生考勤状态管理
+ * 5. 下拉手势恢复筛选条件
+ * 6. 考勤数据保存和提交
+ */
+
+import { ref, computed } from 'vue'
+import Form from '@/components/Form/index.vue'
+import Td from '@/components/Td/index.vue'
+import SsInput from '@/components/SsInput/index.vue'
+import SsSelect from '@/components/SsSelect/index.vue'
+import SsOnoffButton from '@/components/SsOnoffButton/index.vue'
+import SeatLayout from './components/SeatLayout.vue'
+import SsBottom from '@/components/SsBottom/index.vue'
+
+// ==================== 数据定义 ====================
+
+/**
+ * 表单数据
+ * @property {string} bj - 班级ID
+ * @property {string} rq - 日期
+ * @property {string} jc - 节次 (1-上午, 2-下午, 3-晚上)
+ */
+const formData = ref({
+    bj: '1',
+    rq: '2025年6月31日 星期五',
+    jc: '1', // 默认选中上午
+})
+
+/**
+ * 点名相关状态管理
+ * @property {string} attendanceMode - 当前模式
+ *   - 'overview': 初始完整筛选条件模式
+ *   - 'overview-simple': 双击退出后的简化模式
+ *   - 'attendance': 点名模式
+ * @property {Array} studentList - 学生列表数据
+ * @property {Object} seatLayout - 座位布局配置
+ */
+const attendanceMode = ref('overview')
+const studentList = ref([]) // 学生列表
+const seatLayout = ref({ rows: 5, cols: 10 }) // 座位布局:5行10列
+
+/**
+ * 下拉手势相关状态
+ * 用于在 overview-simple 模式下下拉恢复完整筛选条件
+ */
+const showPullIndicator = ref(false) // 是否显示下拉提示
+const pullStartY = ref(0) // 下拉起始Y坐标
+const pullDistance = ref(0) // 下拉距离
+
+/**
+ * 计算回显文本
+ * 在简化模式下显示的筛选条件摘要
+ * 格式:班级名称 + 日期 + 节次
+ */
+const displayText = computed(() => {
+    const bjText = bjOption.value.find(item => item.v === formData.value.bj)?.n || '未选择班级'
+    const jcText = formData.value.jc === '1' ? '上午' : formData.value.jc === '2' ? '下午' : '晚上'
+    return `${bjText}  ${formData.value.rq}  ${jcText}`
+})
+// ==================== 表单配置 ====================
+
+/**
+ * 表单字段校验配置
+ * 定义各个字段的校验规则
+ */
+const fieldConfigs = {
+    bj: {
+        rules: [{ required: true, message: '班级不能为空' }]
+    },
+    rq: {
+        rules: [{ required: true, message: '日期不能为空' }]
+    },
+    jc: {
+        rules: [{ required: true, message: '请选择节次' }]
+    }
+}
+
+/**
+ * 表单引用
+ * 用于表单校验和数据提交
+ */
+const formRef = ref(null)
+
+/**
+ * 班级下拉框配置
+ * TODO: 从接口获取班级列表数据
+ */
+const bjOption = ref([
+    { n: '一年级一班', v: '1' },
+    { n: '一年级二班', v: '2' }
+    // TODO: 调用 getClassList() 接口获取真实班级数据
+])
+const bjLoading = ref(false) // 班级数据加载状态
+
+// ==================== 事件处理方法 ====================
+
+/**
+ * 班级选择变化处理
+ * 当用户选择不同班级时触发,重新加载该班级的学生数据
+ * @param {string} value - 选中的班级ID
+ * @param {Object} option - 选中的班级选项对象
+ */
+const onXcTypeChange = (value, option) => {
+    console.log('班级选择变化:', value, option)
+    console.log('当前formData.bj:', formData.value.bj)
+
+    // 重新加载学生数据
+    loadStudentData()
+
+    // TODO: 可以在这里添加其他班级变化后的逻辑
+    // 例如:清空之前的考勤记录、重置座位布局等
+}
+
+/**
+ * 加载学生数据
+ * 根据当前选择的班级、日期、节次加载学生列表和座位布局
+ * TODO: 替换为真实的接口调用
+ */
+const loadStudentData = async () => {
+    try {
+        // TODO: 调用真实接口获取学生数据
+        // const response = await getStudentList({
+        //     classId: formData.value.bj,
+        //     date: formData.value.rq,
+        //     period: formData.value.jc
+        // })
+
+        // 模拟学生数据 - 生成5行10列的座位布局
+        const mockStudents = []
+        for (let row = 1; row <= 5; row++) {
+            for (let col = 1; col <= 10; col++) {
+                const studentId = `${row}${col.toString().padStart(2, '0')}`
+                mockStudents.push({
+                    id: studentId,
+                    name: `学生${studentId}`,
+                    code: studentId,
+                    avatar: '/static/logo.png', // 默认头像
+                    row: row,    // 座位行号
+                    col: col,    // 座位列号
+                    status: 81   // 考勤状态:81-出勤, 1-旷课, 11-迟到, 21-早退, 0-请假
+                })
+            }
+        }
+
+        studentList.value = mockStudents
+        seatLayout.value = { rows: 5, cols: 10 }
+
+        console.log('学生数据加载完成:', studentList.value.length)
+    } catch (error) {
+        console.error('加载学生数据失败:', error)
+        uni.showToast({
+            title: '加载学生数据失败',
+            icon: 'none'
+        })
+    }
+}
+
+/**
+ * 处理模式切换
+ * 管理三种模式之间的切换逻辑
+ * @param {string} newMode - 新的模式 ('overview' | 'attendance')
+ */
+const handleModeChange = (newMode) => {
+    console.log('模式切换:', attendanceMode.value, '->', newMode)
+
+    if (newMode === 'overview') {
+        // 从点名模式退出时,进入简化显示模式
+        // 用户需要下拉手势才能恢复完整筛选条件
+        attendanceMode.value = 'overview-simple'
+    } else {
+        // 进入点名模式
+        attendanceMode.value = newMode
+    }
+}
+
+/**
+ * 处理学生状态变化
+ * 当用户点击学生卡片切换考勤状态时触发
+ * @param {Object} statusData - 状态变化数据
+ * @param {string} statusData.studentId - 学生ID
+ * @param {number} statusData.oldStatus - 原状态
+ * @param {number} statusData.newStatus - 新状态
+ */
+const handleStatusChange = (statusData) => {
+    console.log('学生状态变化:', statusData)
+
+    // 更新本地数据
+    const student = studentList.value.find(s => s.id === statusData.studentId)
+    if (student) {
+        student.status = statusData.newStatus
+    }
+
+    // TODO: 调用接口同步状态到后端
+    // await updateStudentStatus({
+    //     studentId: statusData.studentId,
+    //     status: statusData.newStatus,
+    //     classId: formData.value.bj,
+    //     date: formData.value.rq,
+    //     period: formData.value.jc
+    // })
+}
+
+/**
+ * 处理学生卡片点击
+ * 记录用户点击的学生信息,可用于统计分析
+ * @param {Object} student - 被点击的学生对象
+ */
+const handleStudentClick = (student) => {
+    console.log('点击学生:', student)
+
+    // TODO: 可以在这里添加点击统计、学生详情查看等功能
+}
+
+// ==================== 手势处理 ====================
+
+/**
+ * 页面级下拉手势开始处理
+ * 只在 overview-simple 模式下响应,用于恢复完整筛选条件
+ * @param {TouchEvent} e - 触摸事件对象
+ */
+const handlePageTouchStart = (e) => {
+    // 只在简化模式下响应下拉手势
+    if (attendanceMode.value !== 'overview-simple') return
+    // 安全检查,防止 touches 为空导致错误
+    if (!e.touches || !e.touches[0]) return
+
+    pullStartY.value = e.touches[0].clientY
+    pullDistance.value = 0
+}
+
+/**
+ * 页面级下拉手势移动处理
+ * 计算下拉距离并显示视觉反馈
+ * @param {TouchEvent} e - 触摸事件对象
+ */
+const handlePageTouchMove = (e) => {
+    if (attendanceMode.value !== 'overview-simple') return
+    if (!e.touches || !e.touches[0]) return
+
+    const currentY = e.touches[0].clientY
+    pullDistance.value = currentY - pullStartY.value
+
+    // 下拉超过50rpx时显示提示
+    if (pullDistance.value > 50) {
+        showPullIndicator.value = true
+    } else {
+        showPullIndicator.value = false
+    }
+}
+
+/**
+ * 页面级下拉手势结束处理
+ * 根据下拉距离决定是否恢复完整筛选条件
+ */
+const handlePageTouchEnd = () => {
+    if (attendanceMode.value !== 'overview-simple') return
+
+    // 下拉超过100rpx时恢复完整筛选条件
+    if (pullDistance.value > 100) {
+        attendanceMode.value = 'overview'
+    }
+
+    // 重置手势状态
+    showPullIndicator.value = false
+    pullDistance.value = 0
+}
+
+// ==================== 底部按钮配置 ====================
+
+/**
+ * 底部按钮配置
+ * 只在非点名模式下显示,提供取消和保存功能
+ */
+const bottomButtons = [
+    { text: '取消', action: 'back' },
+    { text: '保存', action: 'save' }
+]
+
+/**
+ * 底部按钮事件处理
+ * 处理取消和保存操作
+ * @param {Object} data - 按钮数据
+ * @param {string} data.action - 按钮动作类型
+ */
+const handleBottomAction = (data) => {
+    console.log('底部按钮操作:', data)
+
+    switch(data.action) {
+        case 'cancel':
+            // 取消操作,可以重置数据或其他逻辑
+            console.log('取消操作')
+            break
+        case 'back':
+            // 返回上一页
+            uni.navigateBack()
+            break
+        case 'save':
+            // 保存考勤数据
+            handleSave()
+            break
+    }
+}
+
+/**
+ * 保存学生考勤数据
+ * 收集所有学生的考勤状态并提交到后端
+ * TODO: 替换为真实的接口调用
+ */
+const handleSave = async () => {
+    console.log('保存学生考勤数据')
+
+    try {
+        // 收集所有学生的考勤数据
+        const attendanceData = studentList.value.map(student => ({
+            id: student.id,
+            name: student.name,
+            code: student.code,
+            row: student.row,
+            col: student.col,
+            status: student.status,
+            statusText: getStatusText(student.status)
+        }))
+
+        console.log('所有学生考勤状态:', attendanceData)
+
+        // TODO: 调用接口提交考勤数据
+        // const response = await submitAttendanceData({
+        //     classId: formData.value.bj,
+        //     date: formData.value.rq,
+        //     period: formData.value.jc,
+        //     attendanceList: attendanceData
+        // })
+
+        uni.showToast({
+            title: '保存成功',
+            icon: 'success'
+        })
+
+        // TODO: 保存成功后可以执行其他操作
+        // 例如:返回上一页、清空数据、刷新列表等
+
+    } catch (error) {
+        console.error('保存考勤数据失败:', error)
+        uni.showToast({
+            title: '保存失败',
+            icon: 'none'
+        })
+    }
+}
+
+/**
+ * 获取考勤状态文本
+ * 将数字状态码转换为可读的文本描述
+ * @param {number} status - 状态码
+ * @returns {string} 状态文本
+ */
+const getStatusText = (status) => {
+    switch(status) {
+        case 81: return '出勤'
+        case 1: return '旷课'
+        case 11: return '迟到'
+        case 21: return '早退'
+        case 0: return '请假'
+        default: return '未知'
+    }
+}
+
+// ==================== 页面初始化 ====================
+
+/**
+ * 页面加载时初始化数据
+ * 自动加载默认班级的学生数据
+ */
+loadStudentData()
+
+// ==================== 接口预留 ====================
+
+/**
+ * TODO: 需要实现的接口方法
+ *
+ * 1. getClassList() - 获取班级列表
+ *    返回格式:[{ n: '班级名称', v: '班级ID' }]
+ *
+ * 2. getStudentList(params) - 获取学生列表
+ *    参数:{ classId, date, period }
+ *    返回格式:[{ id, name, code, avatar, row, col, status }]
+ *
+ * 3. updateStudentStatus(params) - 更新学生状态
+ *    参数:{ studentId, status, classId, date, period }
+ *
+ * 4. submitAttendanceData(params) - 提交考勤数据
+ *    参数:{ classId, date, period, attendanceList }
+ *
+ * 5. getAttendanceHistory(params) - 获取历史考勤记录
+ *    参数:{ classId, startDate, endDate }
+ */
 
 </script>
 
-<style>
+<style lang="scss" scoped>
+.filter-area {
+    transition: all 0.3s ease;
+    background-color: #fff;
+
+    // 完整模式(默认)
+    &:not(.simple-mode) {
+        // 显示所有筛选条件
+        opacity: 1;
+    }
+
+    // 简化模式(点名状态下)
+    &.simple-mode {
+        .simple-display {
+            padding: 30rpx 40rpx;
+            background-color: #fff;
+            border-bottom: 2rpx solid #E5E5E5;
+            position: relative;
+
+            .display-text {
+                font-size: 32rpx;
+                font-weight: bold;
+                color: #333;
+                text-align: center;
+                display: block;
+            }
+
+            .pull-indicator {
+                position: absolute;
+                top: 100%;
+                left: 50%;
+                transform: translateX(-50%);
+                background-color: rgba(0, 0, 0, 0.7);
+                color: white;
+                padding: 10rpx 30rpx;
+                border-radius: 20rpx;
+                font-size: 24rpx;
+                opacity: 0;
+                transition: opacity 0.3s ease;
+                z-index: 100;
+
+                &.show {
+                    opacity: 1;
+                }
+
+                .pull-text {
+                    white-space: nowrap;
+                }
+            }
+        }
+    }
+}
+
+.onoff-button-group {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+    align-items: flex-start;
+}
 
+.attendance-area {
+    flex: 1;
+    min-height: 80vh; // 确保有足够的高度显示内容
+    overflow: hidden;
+    background-color: #f5f5f5;
+    padding: 20rpx;
+}
 </style>

+ 248 - 0
pages/kqjl/kqjl_bzrDm_list.vue

@@ -0,0 +1,248 @@
+<template>
+    <!-- 班主任点名列表 -->
+    <view class="list-page">
+        <view class="search-container">
+            <ss-search-button
+                text="新增点名"
+                @click="handleAddDm"
+            />
+        </view>
+        <view class="list-container">
+            <ss-card v-for="item in list" :key="item.time" @click="handleCardClick(item)">
+                <view class="card-content">
+                    <!-- 卡片头部:日期和时间段 -->
+                    <view class="card-header">
+                        <view class="card-date">{{ item.time }}</view>
+                        <view class="card-period">{{ item.period }}</view>
+                    </view>
+
+                    <!-- 班级信息 -->
+                    <view class="card-class">{{ item.class }}</view>
+
+                    <!-- 考勤统计 -->
+                    <view class="attendance-stats">
+                        <!-- 迟到 - 270到360度弧形边框 -->
+                        <view class="stat-item">
+                            <view class="stat-circle late">
+                                <text class="stat-text">迟</text>
+                            </view>
+                            <text class="stat-count">{{ item.chidao }}人</text>
+                        </view>
+
+                        <!-- 旷课 - 红色圆形边框 -->
+                        <view class="stat-item">
+                            <view class="stat-circle absent">
+                                <text class="stat-text">旷</text>
+                            </view>
+                            <text class="stat-count">{{ item.kongke }}人</text>
+                        </view>
+
+                        <!-- 早退 - 180到270度弧形边框 -->
+                        <view class="stat-item">
+                            <view class="stat-circle early">
+                                <text class="stat-text">退</text>
+                            </view>
+                            <text class="stat-count">{{ item.zaotui }}人</text>
+                        </view>
+
+                        <!-- 请假 - 图标显示 -->
+                        <view class="stat-item">
+                            <view class="stat-icon-wrapper">
+                                <Icon name="icon-qingjia" size="32" color="#FFA500" />
+                            </view>
+                            <text class="stat-count">{{ item.qingjia }}人</text>
+                        </view>
+                    </view>
+                </view>
+            </ss-card>
+        </view>
+    </view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import SsSearchButton from '@/components/SsSearchButton/index.vue'
+import SsCard from '@/components/SsCard/index.vue'
+import Icon from '@/components/icon/index.vue'
+
+const handleAddDm = () => {
+    console.log('点击了新增点名')
+    uni.navigateTo({
+        url: '/pages/kqjl/kqjl_bzrDm'
+    })
+   
+}
+
+const handleCardClick = (item) => {
+    console.log('点击了卡片', item)
+    uni.showToast({
+        title: `点击了${item.time} ${item.period}的点名`,
+        icon: 'none'
+    })
+}
+
+const list = ref([
+    {
+        time: '2025/06/30',
+        period: "上午",
+        class: '一年级一班',
+        chidao: 10,
+        zaotui: 0,
+        kongke: 1,
+        qingjia: 2,
+    },
+    {
+        time: '2025/06/29',
+        period: "晚上",
+        class: '一年级一班',
+        chidao: 10,
+        zaotui: 1,
+        kongke: 0,
+        qingjia: 2,
+    }
+])
+</script>
+
+<style lang="scss" scoped>
+.list-page {
+    padding: 20rpx;
+    background-color: #f5f5f5;
+    min-height: 100vh;
+
+    .search-container {
+        display: flex;
+        justify-content: flex-end;
+        margin-bottom: 30rpx;
+    }
+
+    .list-container {
+        .card-content {
+            .card-header {
+                display: flex;
+                justify-content: flex-start;
+                align-items: center;
+                margin-bottom: 20rpx;
+
+                .card-date {
+                    font-size: 32rpx;
+                    font-weight: bold;
+                    color: #333;
+                }
+
+                .card-period {
+                    margin-left: 60rpx;
+                    font-size: 32rpx;
+                    font-weight: bold;
+                    color: #333;
+                }
+            }
+
+            .card-class {
+                font-size: 28rpx;
+                color: #666;
+                margin-bottom: 30rpx;
+            }
+
+            .attendance-stats {
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+
+                .stat-item {
+                    display: flex;
+                    // flex-direction: column;
+                    align-items: center;
+                    gap: 10rpx;
+                    flex: 1;
+
+                    .stat-count {
+                        font-size: 24rpx;
+                        color: #333;
+                        text-align: center;
+                    }
+                }
+
+
+
+                // 圆形统计样式基础
+                .stat-circle {
+                    width: 40rpx;
+                    height: 40rpx;
+                    border-radius: 50%;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    position: relative;
+                    background: #fff;
+                    // 基础灰色圆形边框 - 保持4rpx
+                    border: 4rpx solid #E5E5E5;
+
+                    .stat-text {
+                        font-size: 20rpx;  // 字体也相应缩小
+                        font-weight: bold;
+                        z-index: 10;
+                        position: relative;
+                    }
+                }
+
+                // 迟到样式 - 270到360度弧形边框(左上角四分之一)
+                .stat-circle.late {
+
+                    // 创建左上角四分之一弧形 - 适配40rpx圆形
+                    &::before {
+                        content: '';
+                        position: absolute;
+                        top: -4rpx;   // 保持4rpx边框
+                        left: -4rpx;  // 保持4rpx边框
+                        width: 23rpx; // 按比例缩小 (34*40/60≈23)
+                        height: 23rpx;
+                        border: 4rpx solid transparent;
+                        border-left: 4rpx solid #FF4444;
+                        border-top: 4rpx solid #FF4444;
+                        border-radius: 23rpx 0 0 0;
+                        z-index: 5;
+                    }
+                }
+
+                // 旷课样式 - 红色圆形边框(全遮住)
+                .stat-circle.absent {
+                    border: 4rpx solid #FF4444;  // 保持4rpx边框
+
+
+                }
+
+                // 早退样式 - 180到270度弧形边框(左下角四分之一)
+                .stat-circle.early {
+
+
+                    // 创建左下角四分之一弧形 - 适配40rpx圆形
+                    &::before {
+                        content: '';
+                        position: absolute;
+                        top: 17rpx;   // 调整位置 (26*40/60≈17)
+                        left: -4rpx;  // 保持4rpx边框
+                        width: 23rpx; // 按比例缩小
+                        height: 23rpx;
+                        border: 4rpx solid transparent;
+                        border-left: 4rpx solid #FF4444;
+                        border-bottom: 4rpx solid #FF4444;
+                        border-radius: 0 0 0 23rpx;
+                        z-index: 5;
+                    }
+                }
+
+                // 请假图标样式 - 无边框
+                .stat-icon-wrapper {
+                    width: 40rpx;   // 与圆形保持一致
+                    height: 40rpx;  // 与圆形保持一致
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    background: transparent;
+                    border: none;
+                }
+            }
+        }
+    }
+}
+</style>

+ 3 - 36
pages/xfjl/index.vue

@@ -1,9 +1,8 @@
 <template>
-    <view class="xfjl-page">
+    <view class="list-page">
        
         <!-- 搜索按钮区域 -->
-        <view class="search-container right">
-            
+        <view class="search-container">
             <ss-search-button
                 text="充值"
                 pre-icon="icon-jiahao"
@@ -50,13 +49,7 @@ const handleAddRecord = () => {
     })
 }
 
-const handleExport = () => {
-    console.log('点击了导出记录')
-    uni.showToast({
-        title: '导出记录功能',
-        icon: 'none'
-    })
-}
+
 
 // 模拟数据
 const records = [
@@ -99,32 +92,6 @@ const handleCardClick = (record) => {
 </script>
 
 <style lang="scss" scoped>
-.xfjl-page {
-    padding: 20rpx;
-    background-color: #f5f5f5;
-    min-height: 100vh;
-}
-
-.page-header {
-    text-align: center;
-    margin-bottom: 40rpx;
-}
-
-.page-title {
-    font-size: 36rpx;
-    font-weight: bold;
-    color: #333;
-}
-
-.search-container {
-    display: flex;
-    margin: 1rem 0;
-    gap: 0.5rem;
-  
-    &.right {
-        justify-content: flex-end;
-    }
-}
 
 .record-list {
     margin-top: 40rpx;

+ 0 - 1
pages/xuncha/mp_excelRcXcdjl_edit.vue

@@ -1,7 +1,6 @@
 <template>
 	<!-- <view> 日程id : {{ rcid }}</view> -->
 	<Form :rules="fieldConfigs" v-model="formData" ref="formRef" style="height: calc(100vh - 212rpx);">
-
 		<!-- 循环遍历巡查点数据 -->
 		<view v-for="(item, index) in xunchaList" :key="item.xcdid">
 			<table-title>{{ item.xcdmc }}</table-title>

+ 15 - 0
static/css/main.scss

@@ -45,6 +45,7 @@ td {
     height: 100% !important;
 	display: flex !important;
 }
+
 ss-input {
     width: 100% !important;
 }
@@ -56,4 +57,18 @@ ss-datetime-picker {
 }
 .u-toolbar__wrapper__confirm{
     color: #000000 !important;
+}
+
+// 列表页面通用样式
+.list-page {
+    padding: 20rpx;
+    background-color: #f5f5f5;
+    min-height: 100vh;
+}
+// 列表页面搜索区域
+.search-container {
+    display: flex;
+    margin: 1rem 0;
+    gap: 0.5rem;
+    justify-content: flex-end;
 }

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin-devtools/components/Td/index.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin-devtools/pages/kqjl/kqjl_bzrDm.js.map


+ 1 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/api/xuncha.js.map

@@ -1 +1 @@
-{"version":3,"file":"xuncha.js","sources":["api/xuncha.js"],"sourcesContent":["import request from \"@/utils/request\";\n\nexport const xunchaApi = {\n  // 初始化巡查编辑数据 - 获取巡查点列表和记录\n  initZxxzEdit(data) {\n    return request.post(\n      `/service?ssServ=rcXcdjl_initZxxzEdit&ssDest=init&rcid=${data.rcid}`,\n      data,\n      {\n        loading: true\n      }\n    );\n  },\n\n  // 提交巡查编辑数据 - 保存巡查记录(使用表单格式)\n  submZxxzEdit(data, onComplete) {\n    const promise = request.post(\n      `/service?ssServ=rcXcdjl_submZxxzEdit&ssDest=info`,\n      data,\n      {\n        loading: true,\n        formData: true  // 使用表单格式提交\n      }\n    );\n\n    // 如果有完成回调,无论成功还是失败都调用\n    if (onComplete) {\n      promise.finally(() => {\n        onComplete()\n      })\n    }\n\n    return promise;\n  }\n};\n"],"names":["xunchaApi","data","request","onComplete","promise"],"mappings":"oDAEaA,EAAY,CAEvB,aAAaC,EAAM,CACjB,OAAOC,EAAO,QAAC,KACb,yDAAyDD,EAAK,IAAI,GAClEA,EACA,CACE,QAAS,EACV,CACP,CACG,EAGD,aAAaA,EAAME,EAAY,CAC7B,MAAMC,EAAUF,EAAAA,QAAQ,KACtB,mDACAD,EACA,CACE,QAAS,GACT,SAAU,EACX,CACP,EAGI,OAAIE,GACFC,EAAQ,QAAQ,IAAM,CACpBD,EAAY,CACpB,CAAO,EAGIC,CACR,CACH"}
+{"version":3,"file":"xuncha.js","sources":["api/xuncha.js"],"sourcesContent":["//  巡查api\nimport request from \"@/utils/request\";\n\nexport const xunchaApi = {\n  // 初始化巡查编辑数据 - 获取巡查点列表和记录\n  initZxxzEdit(data) {\n    return request.post(\n      `/service?ssServ=rcXcdjl_initZxxzEdit&ssDest=init&rcid=${data.rcid}`,\n      data,\n      {\n        loading: true\n      }\n    );\n  },\n\n  // 提交巡查编辑数据 - 保存巡查记录(使用表单格式)\n  submZxxzEdit(data, onComplete) {\n    const promise = request.post(\n      `/service?ssServ=rcXcdjl_submZxxzEdit&ssDest=info`,\n      data,\n      {\n        loading: true,\n        formData: true  // 使用表单格式提交\n      }\n    );\n\n    // 如果有完成回调,无论成功还是失败都调用\n    if (onComplete) {\n      promise.finally(() => {\n        onComplete()\n      })\n    }\n\n    return promise;\n  }\n};\n"],"names":["xunchaApi","data","request","onComplete","promise"],"mappings":"oDAGaA,EAAY,CAEvB,aAAaC,EAAM,CACjB,OAAOC,EAAO,QAAC,KACb,yDAAyDD,EAAK,IAAI,GAClEA,EACA,CACE,QAAS,EACV,CACP,CACG,EAGD,aAAaA,EAAME,EAAY,CAC7B,MAAMC,EAAUF,EAAAA,QAAQ,KACtB,mDACAD,EACA,CACE,QAAS,GACT,SAAU,EACX,CACP,EAGI,OAAIE,GACFC,EAAQ,QAAQ,IAAM,CACpBD,EAAY,CACpB,CAAO,EAGIC,CACR,CACH"}

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/components/SsOnoffButton/index.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/components/SsSelect/index.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/components/SeatLayout.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/components/StudentCard.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/kqjl_bzrDm.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/kqjl/kqjl_bzrDm_list.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/xfjl/index.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.js.map


+ 1 - 1
unpackage/dist/dev/mp-weixin/app.js

@@ -1,2 +1,2 @@
-"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./common/vendor.js"),i=require("./api/user.js"),a=require("./store/index.js"),s={onLaunch:function(){if(!e.index.getStorageSync("deviceInfo")){const n=e.index.getDeviceInfo();e.index.setStorageSync("deviceInfo",n),e.index.__f__("log","at App.vue:10","初始化设备信息",n)}},onShow:async function(){const n=e.index.getStorageSync("userInfo");if(n!=null&&n.yhsbToken)try{e.index.__f__("log","at App.vue:18","自动登录",n.yhsbToken);const t=await i.userApi.autoLogin({mdToken:n.yhsbToken});e.index.__f__("log","at App.vue:22","自动登录",t.data),e.index.setStorageSync("userInfo",t.data)}catch(t){e.index.__f__("error","at App.vue:28","自动登录失败",t)}else e.index.__f__("log","at App.vue:33","无token,跳过自动登录")},onHide:function(){e.index.__f__("log","at App.vue:37","App Hide")}};function o(){const n=e.createSSRApp(s);return n.use(a.pinia),n.use(e.uviewPlus),{app:n}}o().app.mount("#app");exports.createApp=o;
+"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./common/vendor.js"),i=require("./api/user.js"),s=require("./store/index.js"),a={onLaunch:function(){if(!e.index.getStorageSync("deviceInfo")){const n=e.index.getDeviceInfo();e.index.setStorageSync("deviceInfo",n),e.index.__f__("log","at App.vue:10","初始化设备信息",n)}},onShow:async function(){const n=e.index.getStorageSync("userInfo");if(n!=null&&n.yhsbToken)try{e.index.__f__("log","at App.vue:18","自动登录",n.yhsbToken);const t=await i.userApi.autoLogin({mdToken:n.yhsbToken});e.index.__f__("log","at App.vue:22","自动登录",t.data),e.index.setStorageSync("userInfo",t.data)}catch(t){e.index.__f__("error","at App.vue:28","自动登录失败",t)}else e.index.__f__("log","at App.vue:33","无token,跳过自动登录")},onHide:function(){e.index.__f__("log","at App.vue:37","App Hide")}};function o(){const n=e.createSSRApp(a);return n.use(s.pinia),n.use(e.uviewPlus),{app:n}}o().app.mount("#app");exports.createApp=o;
 //# sourceMappingURL=../.sourcemap/mp-weixin/app.js.map

+ 1 - 0
unpackage/dist/dev/mp-weixin/app.json

@@ -3,6 +3,7 @@
     "pages/index/index",
     "pages/my/index",
     "pages/xuncha/mp_excelRcXcdjl_edit",
+    "pages/kqjl/kqjl_bzrDm_list",
     "pages/kqjl/kqjl_bzrDm",
     "pages/xfjl/index",
     "pages/parent/in-out",

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/app.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/common/vendor.js


+ 1 - 1
unpackage/dist/dev/mp-weixin/components/Form/index.wxss

@@ -1 +1 @@
-.u-table.data-v-354b68fa{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-354b68fa{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-354b68fa{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-354b68fa{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-354b68fa{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-354b68fa{width:100%!important}ss-select.data-v-354b68fa{width:100%!important}ss-datetime-picker.data-v-354b68fa{width:100%!important}.u-toolbar__wrapper__confirm.data-v-354b68fa{color:#000!important}.smart-form.data-v-354b68fa{width:100%}
+.u-table.data-v-354b68fa{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-354b68fa{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-354b68fa{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-354b68fa{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-354b68fa{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-354b68fa{width:100%!important}ss-select.data-v-354b68fa{width:100%!important}ss-datetime-picker.data-v-354b68fa{width:100%!important}.u-toolbar__wrapper__confirm.data-v-354b68fa{color:#000!important}.list-page.data-v-354b68fa{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-354b68fa{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.smart-form.data-v-354b68fa{width:100%}

+ 1 - 1
unpackage/dist/dev/mp-weixin/components/SsBottom/index.wxss

@@ -1 +1 @@
-.u-table.data-v-b930fedb{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-b930fedb{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-b930fedb{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-b930fedb{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-b930fedb{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-b930fedb{width:100%!important}ss-select.data-v-b930fedb{width:100%!important}ss-datetime-picker.data-v-b930fedb{width:100%!important}.u-toolbar__wrapper__confirm.data-v-b930fedb{color:#000!important}.bottom.data-v-b930fedb{position:fixed;bottom:0;left:0;width:100%;z-index:999}.bottom-button-div.data-v-b930fedb{display:flex;justify-content:space-between;align-items:center;background-color:#fff;height:100rpx}.bottom-button.data-v-b930fedb{flex:1;height:100%;line-height:100rpx;text-align:center;font-size:32rpx;color:#333;background-color:#fafafb}.button-divider.data-v-b930fedb{width:1rpx;height:80%;background-color:#e0e0e0}.bottom-button.data-v-b930fedb:active{background-color:#585e6e;color:#fff}
+.u-table.data-v-b930fedb{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-b930fedb{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-b930fedb{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-b930fedb{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-b930fedb{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-b930fedb{width:100%!important}ss-select.data-v-b930fedb{width:100%!important}ss-datetime-picker.data-v-b930fedb{width:100%!important}.u-toolbar__wrapper__confirm.data-v-b930fedb{color:#000!important}.list-page.data-v-b930fedb{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-b930fedb{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.bottom.data-v-b930fedb{position:fixed;bottom:0;left:0;width:100%;z-index:999}.bottom-button-div.data-v-b930fedb{display:flex;justify-content:space-between;align-items:center;background-color:#fff;height:100rpx}.bottom-button.data-v-b930fedb{flex:1;height:100%;line-height:100rpx;text-align:center;font-size:32rpx;color:#333;background-color:#fafafb}.button-divider.data-v-b930fedb{width:1rpx;height:80%;background-color:#e0e0e0}.bottom-button.data-v-b930fedb:active{background-color:#585e6e;color:#fff}

+ 1 - 1
unpackage/dist/dev/mp-weixin/components/SsCard/index.wxss

@@ -1 +1 @@
-.u-table.data-v-9c884cfa{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-9c884cfa{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-9c884cfa{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-9c884cfa{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-9c884cfa{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-9c884cfa{width:100%!important}ss-select.data-v-9c884cfa{width:100%!important}ss-datetime-picker.data-v-9c884cfa{width:100%!important}.u-toolbar__wrapper__confirm.data-v-9c884cfa{color:#000!important}.ss-card.data-v-9c884cfa{background:#fff;border-radius:8rpx;overflow:hidden;padding:25rpx;border:1px solid #d9d9d9;margin-bottom:30rpx;box-shadow:2rpx 6rpx 6rpx rgba(4,0,0,.15);box-sizing:border-box}
+.u-table.data-v-9c884cfa{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-9c884cfa{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-9c884cfa{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-9c884cfa{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-9c884cfa{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-9c884cfa{width:100%!important}ss-select.data-v-9c884cfa{width:100%!important}ss-datetime-picker.data-v-9c884cfa{width:100%!important}.u-toolbar__wrapper__confirm.data-v-9c884cfa{color:#000!important}.list-page.data-v-9c884cfa{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-9c884cfa{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.ss-card.data-v-9c884cfa{background:#fff;border-radius:8rpx;overflow:hidden;padding:25rpx;border:1px solid #d9d9d9;margin-bottom:30rpx;box-shadow:2rpx 6rpx 6rpx rgba(4,0,0,.15);box-sizing:border-box}

+ 1 - 1
unpackage/dist/dev/mp-weixin/components/SsInput/index.wxss

@@ -1 +1 @@
-.u-table.data-v-8a0c74ed{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-8a0c74ed{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-8a0c74ed{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-8a0c74ed{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-8a0c74ed{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-8a0c74ed{width:100%!important}ss-select.data-v-8a0c74ed{width:100%!important}ss-datetime-picker.data-v-8a0c74ed{width:100%!important}.u-toolbar__wrapper__confirm.data-v-8a0c74ed{color:#000!important}.smart-input.data-v-8a0c74ed{width:100%}.smart-input__field.data-v-8a0c74ed{width:100%;height:60rpx;font-size:32rpx;line-height:60rpx;color:#333;background-color:transparent;border:none;outline:none;box-sizing:border-box}.smart-input__field.data-v-8a0c74ed::-webkit-input-placeholder{color:#999;font-size:32rpx}.smart-input__field.data-v-8a0c74ed::placeholder{color:#999;font-size:32rpx}.smart-input__field.data-v-8a0c74ed:focus{color:#333;border:1px solid #ccc}
+.u-table.data-v-8a0c74ed{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-8a0c74ed{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-8a0c74ed{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-8a0c74ed{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-8a0c74ed{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-8a0c74ed{width:100%!important}ss-select.data-v-8a0c74ed{width:100%!important}ss-datetime-picker.data-v-8a0c74ed{width:100%!important}.u-toolbar__wrapper__confirm.data-v-8a0c74ed{color:#000!important}.list-page.data-v-8a0c74ed{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-8a0c74ed{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.smart-input.data-v-8a0c74ed{width:100%}.smart-input__field.data-v-8a0c74ed{width:100%;height:60rpx;font-size:32rpx;line-height:60rpx;color:#333;background-color:transparent;border:none;outline:none;box-sizing:border-box}.smart-input__field.data-v-8a0c74ed::-webkit-input-placeholder{color:#999;font-size:32rpx}.smart-input__field.data-v-8a0c74ed::placeholder{color:#999;font-size:32rpx}.smart-input__field.data-v-8a0c74ed:focus{color:#333;border:1px solid #ccc}

+ 2 - 0
unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.js

@@ -0,0 +1,2 @@
+"use strict";const r=require("../../common/vendor.js"),f={__name:"index",props:{name:{type:String,required:!0},label:{type:String,required:!0},value:{type:[String,Number],required:!0},width:{type:String,default:""},modelValue:{type:[String,Number,Array],default:""},multiple:{type:Boolean,default:!1}},emits:["update:modelValue","change"],setup(a,{emit:d}){const e=a,l=d,s=r.inject("validateField",()=>{}),i=t=>{if(!t)return[];if(Array.isArray(t))return t.map(u=>u.toString());const n=t.toString().replace(/^,+/,"");return n.includes("|")?n.split("|"):n.includes(",")?n.split(","):n?[n]:[]},o=r.computed(()=>e.multiple?i(e.modelValue).includes(e.value.toString()):e.modelValue===e.value),m=()=>{if(e.multiple){const t=i(e.modelValue),n=t.indexOf(e.value.toString());let u;n===-1?u=[...t,e.value.toString()]:u=t.filter(p=>p!==e.value.toString());const c=u.join(",");l("update:modelValue",c),l("change",c,u)}else l("update:modelValue",e.value),l("change",e.value);r.nextTick$1(()=>{e.name&&s(e.name)})};return(t,n)=>({a:r.t(a.label),b:r.n(o.value?"form-icon-onoffbutton-checked":"form-icon-onoffbutton-unchecked"),c:o.value?1:"",d:r.o(m),e:r.gei(t,"")})}},g=r._export_sfc(f,[["__scopeId","data-v-b253cbc5"]]);wx.createComponent(g);
+//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/SsOnoffButton/index.js.map

+ 4 - 0
unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.wxml

@@ -0,0 +1 @@
+<view class="{{['ss-onoff-button', 'data-v-b253cbc5', c && 'checked', virtualHostClass]}}" bindtap="{{d}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{e}}"><text class="button-label data-v-b253cbc5">{{a}}</text><view class="button-mark data-v-b253cbc5"><text class="{{['form-icon', 'data-v-b253cbc5', b]}}"></text></view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/components/SsOnoffButton/index.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/components/SsSearchButton/index.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/components/SsSelect/index.js


+ 6 - 0
unpackage/dist/dev/mp-weixin/components/SsSelect/index.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "icon": "../icon/index"
+  }
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/components/SsSelect/index.wxml

@@ -0,0 +1 @@
+<view class="{{['ss-select-container', 'data-v-ac2d57b0', j && 'open', virtualHostClass]}}" catchtap="{{k}}" style="{{l + ';' + virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{m}}"><view class="{{['ss-select', 'data-v-ac2d57b0', e && 'disabled']}}"><text class="{{['select-text', 'data-v-ac2d57b0', b && 'placeholder']}}">{{a}}</text><view class="{{['select-arrow', 'data-v-ac2d57b0', d && 'rotate']}}"><icon wx:if="{{c}}" class="data-v-ac2d57b0" virtualHostClass="data-v-ac2d57b0" u-i="ac2d57b0-0" bind:__l="__l" u-p="{{c}}"/></view></view><view class="ss-options data-v-ac2d57b0" hidden="{{!i}}"><view wx:if="{{f}}" class="option-item loading-item data-v-ac2d57b0"><text class="loading-text data-v-ac2d57b0">加载中...</text></view><view wx:elif="{{g}}" class="option-item no-options data-v-ac2d57b0"> 无选项 </view><block wx:else><view wx:for="{{h}}" wx:for-item="option" wx:key="b" class="{{['option-item', 'data-v-ac2d57b0', option.c && 'selected']}}" catchtap="{{option.d}}">{{option.a}}</view></block></view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/components/SsSelect/index.wxss


+ 1 - 1
unpackage/dist/dev/mp-weixin/components/SsTableTitle/index.wxss

@@ -1 +1 @@
-.u-table.data-v-1685171e{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-1685171e{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-1685171e{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-1685171e{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-1685171e{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-1685171e{width:100%!important}ss-select.data-v-1685171e{width:100%!important}ss-datetime-picker.data-v-1685171e{width:100%!important}.u-toolbar__wrapper__confirm.data-v-1685171e{color:#000!important}.table-title.data-v-1685171e{width:calc(100% - 32rpx);margin:16rpx auto;font-size:32rpx;color:#333}
+.u-table.data-v-1685171e{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-1685171e{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-1685171e{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-1685171e{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-1685171e{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-1685171e{width:100%!important}ss-select.data-v-1685171e{width:100%!important}ss-datetime-picker.data-v-1685171e{width:100%!important}.u-toolbar__wrapper__confirm.data-v-1685171e{color:#000!important}.list-page.data-v-1685171e{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-1685171e{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.table-title.data-v-1685171e{width:calc(100% - 32rpx);margin:16rpx auto;font-size:32rpx;color:#333}

Разница между файлами не показана из-за своего большого размера
+ 0 - 1
unpackage/dist/dev/mp-weixin/components/Td/index.wxss


+ 1 - 1
unpackage/dist/dev/mp-weixin/components/tabbar/index.wxss

@@ -1 +1 @@
-.u-table.data-v-0e399a7b{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-0e399a7b{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-0e399a7b{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-0e399a7b{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-0e399a7b{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-0e399a7b{width:100%!important}ss-select.data-v-0e399a7b{width:100%!important}ss-datetime-picker.data-v-0e399a7b{width:100%!important}.u-toolbar__wrapper__confirm.data-v-0e399a7b{color:#000!important}.custom-tabbar.data-v-0e399a7b{position:fixed;left:0;bottom:0;width:100%;height:120rpx;align-items:center;background-color:#fff;display:flex;border-top:1rpx solid #dcdcdc;z-index:999}.custom-tabbar.safe-area-inset-bottom.data-v-0e399a7b{padding-bottom:constant(safe-area-inset-bottom);padding-bottom:env(safe-area-inset-bottom)}.custom-tabbar .tabbar-item.data-v-0e399a7b{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}.custom-tabbar .tabbar-item .icon-box.data-v-0e399a7b{margin-bottom:6rpx}.custom-tabbar .tabbar-item .text.data-v-0e399a7b{font-size:24rpx;line-height:1}
+.u-table.data-v-0e399a7b{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-0e399a7b{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-0e399a7b{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-0e399a7b{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-0e399a7b{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-0e399a7b{width:100%!important}ss-select.data-v-0e399a7b{width:100%!important}ss-datetime-picker.data-v-0e399a7b{width:100%!important}.u-toolbar__wrapper__confirm.data-v-0e399a7b{color:#000!important}.list-page.data-v-0e399a7b{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-0e399a7b{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.custom-tabbar.data-v-0e399a7b{position:fixed;left:0;bottom:0;width:100%;height:120rpx;align-items:center;background-color:#fff;display:flex;border-top:1rpx solid #dcdcdc;z-index:999}.custom-tabbar.safe-area-inset-bottom.data-v-0e399a7b{padding-bottom:constant(safe-area-inset-bottom);padding-bottom:env(safe-area-inset-bottom)}.custom-tabbar .tabbar-item.data-v-0e399a7b{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center}.custom-tabbar .tabbar-item .icon-box.data-v-0e399a7b{margin-bottom:6rpx}.custom-tabbar .tabbar-item .text.data-v-0e399a7b{font-size:24rpx;line-height:1}

+ 1 - 1
unpackage/dist/dev/mp-weixin/node-modules/uview-plus/components/u-th/u-th.wxss

@@ -1 +1 @@
-.u-table.data-v-834ef5b3{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-834ef5b3{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-834ef5b3{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-834ef5b3{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-834ef5b3{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-834ef5b3{width:100%!important}ss-select.data-v-834ef5b3{width:100%!important}ss-datetime-picker.data-v-834ef5b3{width:100%!important}.u-toolbar__wrapper__confirm.data-v-834ef5b3{color:#000!important}.u-th.data-v-834ef5b3{display:flex;flex-direction:row;flex-direction:column;flex:1;justify-content:center;font-size:28rpx;color:#303133;font-weight:700;background-color:#f5f6f8}
+.u-table.data-v-834ef5b3{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-834ef5b3{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-834ef5b3{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-834ef5b3{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-834ef5b3{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-834ef5b3{width:100%!important}ss-select.data-v-834ef5b3{width:100%!important}ss-datetime-picker.data-v-834ef5b3{width:100%!important}.u-toolbar__wrapper__confirm.data-v-834ef5b3{color:#000!important}.list-page.data-v-834ef5b3{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-834ef5b3{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.u-th.data-v-834ef5b3{display:flex;flex-direction:row;flex-direction:column;flex:1;justify-content:center;font-size:28rpx;color:#303133;font-weight:700;background-color:#f5f6f8}

+ 1 - 1
unpackage/dist/dev/mp-weixin/node-modules/uview-plus/components/u-tr/u-tr.wxss

@@ -1 +1 @@
-.u-table.data-v-5d3bd056{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-5d3bd056{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-5d3bd056{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-5d3bd056{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-5d3bd056{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-5d3bd056{width:100%!important}ss-select.data-v-5d3bd056{width:100%!important}ss-datetime-picker.data-v-5d3bd056{width:100%!important}.u-toolbar__wrapper__confirm.data-v-5d3bd056{color:#000!important}.u-tr.data-v-5d3bd056{display:flex;flex-direction:row}
+.u-table.data-v-5d3bd056{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-5d3bd056{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-5d3bd056{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-5d3bd056{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-5d3bd056{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-5d3bd056{width:100%!important}ss-select.data-v-5d3bd056{width:100%!important}ss-datetime-picker.data-v-5d3bd056{width:100%!important}.u-toolbar__wrapper__confirm.data-v-5d3bd056{color:#000!important}.list-page.data-v-5d3bd056{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-5d3bd056{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.u-tr.data-v-5d3bd056{display:flex;flex-direction:row}

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/index/index.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/index/index.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.js


+ 6 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.json

@@ -0,0 +1,6 @@
+{
+  "component": true,
+  "usingComponents": {
+    "student-card": "./StudentCard"
+  }
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.wxml

@@ -0,0 +1 @@
+<view class="{{['seat-layout-container', 'data-v-2c702716', virtualHostClass]}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{o}}"><view wx:if="{{a}}" class="seat-layout overview-mode data-v-2c702716" style="{{g}}"><view class="overview-content data-v-2c702716" style="{{d}}" bindtouchstart="{{e}}" bindtouchend="{{f}}"><view class="seat-grid data-v-2c702716" style="{{c}}"><student-card wx:for="{{b}}" wx:for-item="student" wx:key="a" class="data-v-2c702716" virtualHostClass="data-v-2c702716" style="{{student.b}}" virtualHostStyle="{{student.b}}" bindstatusChange="{{student.c}}" bindclick="{{student.d}}" u-i="{{student.e}}" bind:__l="__l" u-p="{{student.f}}"/></view></view></view><scroll-view wx:else ref="scrollViewRef" class="seat-layout attendance-mode data-v-2c702716" scroll-x="true" scroll-y="true" enable-flex="true" scroll-top="{{k}}" scroll-left="{{l}}" bindtouchstart="{{m}}" bindtouchend="{{n}}"><view class="scroll-content data-v-2c702716" style="{{j}}"><view class="seat-grid data-v-2c702716" style="{{i}}"><student-card wx:for="{{h}}" wx:for-item="student" wx:key="a" class="data-v-2c702716" virtualHostClass="data-v-2c702716" style="{{student.b}}" virtualHostStyle="{{student.b}}" bindstatusChange="{{student.c}}" bindclick="{{student.d}}" u-i="{{student.e}}" bind:__l="__l" u-p="{{student.f}}"/></view></view></scroll-view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/SeatLayout.wxss


+ 2 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.js

@@ -0,0 +1,2 @@
+"use strict";const t=require("../../../common/vendor.js"),o={__name:"StudentCard",props:{student:{type:Object,required:!0,default:()=>({id:"",name:"",code:"",avatar:"",row:1,col:1,status:81})},attendanceMode:{type:Boolean,default:!1}},emits:["click","statusChange"],setup(e,{emit:d}){const a=e,s=d,u=()=>{if(t.index.__f__("log","at pages/kqjl/components/StudentCard.vue:95","点击了学生卡片:",a.student.name,"当前模式:",a.attendanceMode),!a.attendanceMode){t.index.__f__("log","at pages/kqjl/components/StudentCard.vue:97","不在点名模式,忽略点击");return}t.index.__f__("log","at pages/kqjl/components/StudentCard.vue:101","开始状态切换,当前状态:",a.student.status);let n;switch(a.student.status){case 81:n=1;break;case 1:n=11;break;case 11:n=21;break;case 21:n=81;break;default:n=81}s("statusChange",{studentId:a.student.id,oldStatus:a.student.status,newStatus:n}),s("click",a.student)},c=()=>{t.index.__f__("log","at pages/kqjl/components/StudentCard.vue:133","头像加载失败:",a.student.name)};return(n,i)=>t.e({a:e.student.avatar||"/static/images/default-avatar.png",b:t.o(c),c:t.t(e.student.code),d:t.t(e.student.name),e:e.student.status===11},e.student.status===11?{}:{},{f:e.student.status===1},e.student.status===1?{}:{},{g:e.student.status===21},e.student.status===21?{}:{},{h:t.o(u),i:t.gei(n,"")})}},r=t._export_sfc(o,[["__scopeId","data-v-ab7d66f5"]]);wx.createComponent(r);
+//# sourceMappingURL=../../../../.sourcemap/mp-weixin/pages/kqjl/components/StudentCard.js.map

+ 4 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.wxml

@@ -0,0 +1 @@
+<view bindtap="{{h}}" class="{{['student-card', 'data-v-ab7d66f5', virtualHostClass]}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{i}}"><view class="avatar-container data-v-ab7d66f5"><image class="avatar data-v-ab7d66f5" src="{{a}}" mode="aspectFill" binderror="{{b}}"/></view><view class="student-info data-v-ab7d66f5"><view class="student-code data-v-ab7d66f5">{{c}}</view><view class="student-name data-v-ab7d66f5">{{d}}</view></view><view class="status-line-container data-v-ab7d66f5"><view class="status-line-base data-v-ab7d66f5"></view><view wx:if="{{e}}" class="status-line-overlay status-late-overlay data-v-ab7d66f5"></view><view wx:if="{{f}}" class="status-line-overlay status-absent-overlay data-v-ab7d66f5"></view><view wx:if="{{g}}" class="status-line-overlay status-early-overlay data-v-ab7d66f5"></view></view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/components/StudentCard.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.js


+ 12 - 1
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.json

@@ -1,4 +1,15 @@
 {
   "navigationBarTitleText": "班主任点名",
-  "usingComponents": {}
+  "usingComponents": {
+    "up-th": "../../node-modules/uview-plus/components/u-th/u-th",
+    "up-tr": "../../node-modules/uview-plus/components/u-tr/u-tr",
+    "up-table": "../../node-modules/uview-plus/components/u-table/u-table",
+    "form": "../../components/Form/index",
+    "td": "../../components/Td/index",
+    "ss-input": "../../components/SsInput/index",
+    "ss-select": "../../components/SsSelect/index",
+    "ss-onoff-button": "../../components/SsOnoffButton/index",
+    "seat-layout": "./components/SeatLayout",
+    "ss-bottom": "../../components/SsBottom/index"
+  }
 }

Разница между файлами не показана из-за своего большого размера
+ 0 - 1
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.wxml


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm.wxss


+ 2 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.js

@@ -0,0 +1,2 @@
+"use strict";const e=require("../../common/vendor.js");Math||(i+r+d)();const i=()=>"../../components/SsSearchButton/index.js",d=()=>"../../components/SsCard/index.js",r=()=>"../../components/icon/index.js",_={__name:"kqjl_bzrDm_list",setup(u){const a=()=>{e.index.__f__("log","at pages/kqjl/kqjl_bzrDm_list.vue:69","点击了新增点名"),e.index.navigateTo({url:"/pages/kqjl/kqjl_bzrDm"})},s=n=>{e.index.__f__("log","at pages/kqjl/kqjl_bzrDm_list.vue:77","点击了卡片",n),e.index.showToast({title:`点击了${n.time} ${n.period}的点名`,icon:"none"})},c=e.ref([{time:"2025/06/30",period:"上午",class:"一年级一班",chidao:10,zaotui:0,kongke:1,qingjia:2},{time:"2025/06/29",period:"晚上",class:"一年级一班",chidao:10,zaotui:1,kongke:0,qingjia:2}]);return(n,g)=>({a:e.o(a),b:e.p({text:"新增点名"}),c:e.f(c.value,(o,p,t)=>({a:e.t(o.time),b:e.t(o.period),c:e.t(o.class),d:e.t(o.chidao),e:e.t(o.kongke),f:e.t(o.zaotui),g:"d70c11ed-2-"+t+","+("d70c11ed-1-"+t),h:e.t(o.qingjia),i:o.time,j:e.o(k=>s(o),o.time),k:"d70c11ed-1-"+t})),d:e.p({name:"icon-qingjia",size:"32",color:"#FFA500"}),e:e.gei(n,"")})}},l=e._export_sfc(_,[["__scopeId","data-v-d70c11ed"]]);wx.createPage(l);
+//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/kqjl/kqjl_bzrDm_list.js.map

+ 8 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.json

@@ -0,0 +1,8 @@
+{
+  "navigationBarTitleText": "班主任点名",
+  "usingComponents": {
+    "ss-search-button": "../../components/SsSearchButton/index",
+    "ss-card": "../../components/SsCard/index",
+    "icon": "../../components/icon/index"
+  }
+}

+ 1 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.wxml

@@ -0,0 +1 @@
+<view class="{{['list-page', 'data-v-d70c11ed', virtualHostClass]}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{e}}"><view class="search-container data-v-d70c11ed"><ss-search-button wx:if="{{b}}" class="data-v-d70c11ed" virtualHostClass="data-v-d70c11ed" bindclick="{{a}}" u-i="d70c11ed-0" bind:__l="__l" u-p="{{b}}"/></view><view class="list-container data-v-d70c11ed"><ss-card wx:for="{{c}}" wx:for-item="item" wx:key="i" class="data-v-d70c11ed" virtualHostClass="data-v-d70c11ed" u-s="{{['d']}}" bindclick="{{item.j}}" u-i="{{item.k}}" bind:__l="__l"><view class="card-content data-v-d70c11ed"><view class="card-header data-v-d70c11ed"><view class="card-date data-v-d70c11ed">{{item.a}}</view><view class="card-period data-v-d70c11ed">{{item.b}}</view></view><view class="card-class data-v-d70c11ed">{{item.c}}</view><view class="attendance-stats data-v-d70c11ed"><view class="stat-item data-v-d70c11ed"><view class="stat-circle late data-v-d70c11ed"><text class="stat-text data-v-d70c11ed">迟</text></view><text class="stat-count data-v-d70c11ed">{{item.d}}人</text></view><view class="stat-item data-v-d70c11ed"><view class="stat-circle absent data-v-d70c11ed"><text class="stat-text data-v-d70c11ed">旷</text></view><text class="stat-count data-v-d70c11ed">{{item.e}}人</text></view><view class="stat-item data-v-d70c11ed"><view class="stat-circle early data-v-d70c11ed"><text class="stat-text data-v-d70c11ed">退</text></view><text class="stat-count data-v-d70c11ed">{{item.f}}人</text></view><view class="stat-item data-v-d70c11ed"><view class="stat-icon-wrapper data-v-d70c11ed"><icon wx:if="{{d}}" class="data-v-d70c11ed" virtualHostClass="data-v-d70c11ed" u-i="{{item.g}}" bind:__l="__l" u-p="{{d}}"/></view><text class="stat-count data-v-d70c11ed">{{item.h}}人</text></view></view></view></ss-card></view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/kqjl/kqjl_bzrDm_list.wxss


+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/my/index.wxss

@@ -1 +1 @@
-.u-table.data-v-f97bc692{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-f97bc692{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-f97bc692{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-f97bc692{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-f97bc692{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-f97bc692{width:100%!important}ss-select.data-v-f97bc692{width:100%!important}ss-datetime-picker.data-v-f97bc692{width:100%!important}.u-toolbar__wrapper__confirm.data-v-f97bc692{color:#000!important}.content.data-v-f97bc692{background:#eee;min-height:100vh}
+.u-table.data-v-f97bc692{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-f97bc692{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-f97bc692{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-f97bc692{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-f97bc692{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-f97bc692{width:100%!important}ss-select.data-v-f97bc692{width:100%!important}ss-datetime-picker.data-v-f97bc692{width:100%!important}.u-toolbar__wrapper__confirm.data-v-f97bc692{color:#000!important}.list-page.data-v-f97bc692{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-f97bc692{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}.content.data-v-f97bc692{background:#eee;min-height:100vh}

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/xfjl/index.js

@@ -1,2 +1,2 @@
-"use strict";const e=require("../../common/vendor.js");Math||(c+d)();const c=()=>"../../components/SsSearchButton/index.js",d=()=>"../../components/SsCard/index.js",_={__name:"index",setup(l){const o=()=>{e.index.__f__("log","at pages/xfjl/index.vue:46","点击了新增消费记录"),e.index.showToast({title:"新增消费记录",icon:"none"})},a=[{id:"XFJ-001-20250612122200001",type:"expense",amount:-10,balance:120,time:"2025年6月12日 12:22",location:"第一饭堂001消费机",orderNo:"XFJ-001-20250612122200001"},{id:"XFJ-001-20250612122200002",type:"income",amount:100,balance:120,time:"2025年6月12日 12:22",location:"充值",orderNo:"XFJ-001-20250612122200001"},{id:"XFJ-001-20250612122200003",type:"expense",amount:-15,balance:20,time:"2025年6月12日 11:35",location:"第二饭堂002消费机",orderNo:"XFJ-001-20250612113500001"}],i=t=>{e.index.__f__("log","at pages/xfjl/index.vue:93","点击了记录:",t),e.index.showToast({title:`点击了${t.type==="expense"?"支出":"充值"}记录`,icon:"none"})};return(t,m)=>({a:e.o(o),b:e.p({text:"充值","pre-icon":"icon-jiahao"}),c:e.f(a,(n,u,s)=>({a:e.t(n.amount>0?"+":""),b:e.t(n.amount),c:e.n(n.type),d:e.t(n.balance),e:e.t(n.time),f:e.t(n.location),g:e.t(n.orderNo),h:n.id,i:e.o(x=>i(n),n.id),j:"25784ea2-1-"+s})),d:e.gei(t,"")})}},p=e._export_sfc(_,[["__scopeId","data-v-25784ea2"]]);wx.createPage(p);
+"use strict";const e=require("../../common/vendor.js");Math||(c+d)();const c=()=>"../../components/SsSearchButton/index.js",d=()=>"../../components/SsCard/index.js",_={__name:"index",setup(l){const o=()=>{e.index.__f__("log","at pages/xfjl/index.vue:45","点击了新增消费记录"),e.index.showToast({title:"新增消费记录",icon:"none"})},a=[{id:"XFJ-001-20250612122200001",type:"expense",amount:-10,balance:120,time:"2025年6月12日 12:22",location:"第一饭堂001消费机",orderNo:"XFJ-001-20250612122200001"},{id:"XFJ-001-20250612122200002",type:"income",amount:100,balance:120,time:"2025年6月12日 12:22",location:"充值",orderNo:"XFJ-001-20250612122200001"},{id:"XFJ-001-20250612122200003",type:"expense",amount:-15,balance:20,time:"2025年6月12日 11:35",location:"第二饭堂002消费机",orderNo:"XFJ-001-20250612113500001"}],i=t=>{e.index.__f__("log","at pages/xfjl/index.vue:86","点击了记录:",t),e.index.showToast({title:`点击了${t.type==="expense"?"支出":"充值"}记录`,icon:"none"})};return(t,m)=>({a:e.o(o),b:e.p({text:"充值","pre-icon":"icon-jiahao"}),c:e.f(a,(n,u,s)=>({a:e.t(n.amount>0?"+":""),b:e.t(n.amount),c:e.n(n.type),d:e.t(n.balance),e:e.t(n.time),f:e.t(n.location),g:e.t(n.orderNo),h:n.id,i:e.o(x=>i(n),n.id),j:"25784ea2-1-"+s})),d:e.gei(t,"")})}},p=e._export_sfc(_,[["__scopeId","data-v-25784ea2"]]);wx.createPage(p);
 //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/xfjl/index.js.map

+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/xfjl/index.wxml

@@ -1 +1 @@
-<view class="{{['xfjl-page', 'data-v-25784ea2', virtualHostClass]}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{d}}"><view class="search-container right data-v-25784ea2"><ss-search-button wx:if="{{b}}" class="data-v-25784ea2" virtualHostClass="data-v-25784ea2" bindclick="{{a}}" u-i="25784ea2-0" bind:__l="__l" u-p="{{b}}"/></view><view class="record-list data-v-25784ea2"><ss-card wx:for="{{c}}" wx:for-item="record" wx:key="h" class="data-v-25784ea2" virtualHostClass="data-v-25784ea2" u-s="{{['d']}}" bindclick="{{record.i}}" u-i="{{record.j}}" bind:__l="__l"><view class="record-item data-v-25784ea2"><view class="record-header data-v-25784ea2"><text class="{{['amount', 'data-v-25784ea2', record.c]}}">{{record.a}}¥ {{record.b}}</text><text class="balance data-v-25784ea2">【余额: {{record.d}}】</text></view><view class="record-info data-v-25784ea2"><view class="time data-v-25784ea2">{{record.e}}</view><view class="location data-v-25784ea2">{{record.f}}</view><view class="order-no data-v-25784ea2">{{record.g}}</view></view></view></ss-card></view></view>
+<view class="{{['list-page', 'data-v-25784ea2', virtualHostClass]}}" style="{{virtualHostStyle}}" hidden="{{virtualHostHidden || false}}" id="{{d}}"><view class="search-container data-v-25784ea2"><ss-search-button wx:if="{{b}}" class="data-v-25784ea2" virtualHostClass="data-v-25784ea2" bindclick="{{a}}" u-i="25784ea2-0" bind:__l="__l" u-p="{{b}}"/></view><view class="record-list data-v-25784ea2"><ss-card wx:for="{{c}}" wx:for-item="record" wx:key="h" class="data-v-25784ea2" virtualHostClass="data-v-25784ea2" u-s="{{['d']}}" bindclick="{{record.i}}" u-i="{{record.j}}" bind:__l="__l"><view class="record-item data-v-25784ea2"><view class="record-header data-v-25784ea2"><text class="{{['amount', 'data-v-25784ea2', record.c]}}">{{record.a}}¥ {{record.b}}</text><text class="balance data-v-25784ea2">【余额: {{record.d}}】</text></view><view class="record-info data-v-25784ea2"><view class="time data-v-25784ea2">{{record.e}}</view><view class="location data-v-25784ea2">{{record.f}}</view><view class="order-no data-v-25784ea2">{{record.g}}</view></view></view></ss-card></view></view>

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/xfjl/index.wxss


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
unpackage/dist/dev/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.js


+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/xuncha/mp_excelRcXcdjl_edit.wxss

@@ -1 +1 @@
-.u-table.data-v-134710e1{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-134710e1{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-134710e1{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-134710e1{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-134710e1{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-134710e1{width:100%!important}ss-select.data-v-134710e1{width:100%!important}ss-datetime-picker.data-v-134710e1{width:100%!important}.u-toolbar__wrapper__confirm.data-v-134710e1{color:#000!important}
+.u-table.data-v-134710e1{width:calc(100% - 32rpx);margin:0 auto 1rem;border-left:4rpx solid #f2f2f2!important;border-top:4rpx solid #f2f2f2!important}.u-tr.data-v-134710e1{height:92rpx;display:flex;align-items:center;box-sizing:border-box}.u-th.data-v-134710e1{height:100%;padding-right:32rpx!important;background-color:#fafafa!important;align-items:flex-end;justify-content:flex-end;box-sizing:border-box;max-width:30%;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important;font-weight:400!important}.u-td.data-v-134710e1{height:100%;padding-left:32rpx!important;align-items:flex-start;justify-content:flex-start;box-sizing:border-box;border-bottom:4rpx solid #f2f2f2!important;border-right:4rpx solid #f2f2f2!important;color:#333!important;font-size:32rpx!important}td.data-v-134710e1{flex:1!important;min-width:0!important;width:100%!important;height:100%!important;display:flex!important}ss-input.data-v-134710e1{width:100%!important}ss-select.data-v-134710e1{width:100%!important}ss-datetime-picker.data-v-134710e1{width:100%!important}.u-toolbar__wrapper__confirm.data-v-134710e1{color:#000!important}.list-page.data-v-134710e1{padding:20rpx;background-color:#f5f5f5;min-height:100vh}.search-container.data-v-134710e1{display:flex;margin:1rem 0;gap:.5rem;justify-content:flex-end}

+ 15 - 0
unpackage/dist/dev/mp-weixin/static/css/main.scss

@@ -45,6 +45,7 @@ td {
     height: 100% !important;
 	display: flex !important;
 }
+
 ss-input {
     width: 100% !important;
 }
@@ -56,4 +57,18 @@ ss-datetime-picker {
 }
 .u-toolbar__wrapper__confirm{
     color: #000000 !important;
+}
+
+// 列表页面通用样式
+.list-page {
+    padding: 20rpx;
+    background-color: #f5f5f5;
+    min-height: 100vh;
+}
+// 列表页面搜索区域
+.search-container {
+    display: flex;
+    margin: 1rem 0;
+    gap: 0.5rem;
+    justify-content: flex-end;
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов