Jelajahi Sumber

针对UI图修改列表卡片、更换iconfont为最新的图标

apple 1 Minggu lalu
induk
melakukan
9190a8a773

+ 133 - 11
js/vue/ss-components.js

@@ -2532,7 +2532,7 @@ import { EVEN_VAR } from "./EventBus.js";
     setup(props, { emit, attrs }) {
       // v3.0 分支:有 class 属性时直接渲染(从 attrs 获取) by xu 20251215
       if (attrs.class) {
-        return () => h("i", { class: attrs.class + ' icon-container' });
+        return () => h("i", { ...attrs, class: attrs.class + ' icon-container' });
       }
 
       // v1.0 分支:原有逻辑
@@ -4173,6 +4173,72 @@ import { EVEN_VAR } from "./EventBus.js";
     },
   };
   // ss-list-card 通用列表卡片
+  /**
+   * SsListCard - 列表卡片组件
+   *
+   * @description 用于显示列表项的卡片组件,支持缩略图、标签、状态、操作按钮和选择功能
+   *
+   * @prop {Object} item - 卡片数据对象
+   * @prop {String} item.title - 卡片标题
+   * @prop {String} [item.thumb] - 缩略图 URL(可选)
+   * @prop {String} [item.thumbType] - 缩略图类型:'thumbnail'(缩略图)或默认(证件照)
+   * @prop {String} [item.status] - 卡片状态:'available'(可用-绿色)、'unavailable'(不可用-黄色)、'disabled'(禁用-红色)
+   * @prop {Array} item.tags - 标签数组,格式:[{键: 值}, ...]
+   * @prop {Function} item.onclick - 点击卡片的回调函数
+   * @prop {Array} [item.buttons] - 操作按钮数组(可选),显示在右上角齿轮
+   * @prop {Array} [item.statusIcons] - 状态图标数组(可选),显示在右上角,格式:[{class: '图标类名', title: '提示文字'}, ...]
+   *
+   * @example
+   * // 基础用法
+   * const item = {
+   *   title: "卡片标题",
+   *   tags: [
+   *     { 类型: '文档' },
+   *     { 状态: '进行中' }
+   *   ],
+   *   onclick: () => console.log('点击了卡片')
+   * };
+   *
+   * @example
+   * // 带缩略图和状态
+   * const item = {
+   *   title: "场地预定",
+   *   thumbType: 'thumbnail',
+   *   thumb: "https://example.com/image.jpg",
+   *   status: "available",  // 绿色背景
+   *   tags: [{ 容量: '50人' }],
+   *   onclick: () => {}
+   * };
+   *
+   * @example
+   * // 带操作按钮和状态图标
+   * const item = {
+   *   title: "会议室A",
+   *   tags: [{ 楼层: '3F' }],
+   *   onclick: () => {},
+   *   // 右上角操作按钮(齿轮)
+   *   buttons: [{
+   *     class: 'cart-list-setting',
+   *     title: '编辑',
+   *     onclick: () => console.log('编辑')
+   *   }],
+   *   // 右上角状态图标(在齿轮右边)
+   *   statusIcons: [{
+   *     class: 'icon-emoji',
+   *     title: '清洁中'
+   *   }]
+   * };
+   *
+   * @features
+   * - 卡片选择:鼠标悬停右下角显示选择角标,点击切换选中状态,选中后显示底部深灰色线条
+   * - 状态颜色:根据 status 字段显示不同背景色(可用/不可用/禁用)
+   * - 图片类型:支持证件照(73×100px)和缩略图(180×100px)两种尺寸
+   * - 操作按钮:右上角齿轮,hover 显示,支持多个按钮下拉菜单
+   * - 状态图标:右上角显示状态图标,齿轮会根据图标数量自动左移
+   *
+   * @author xu
+   * @date 20260105
+   */
   const SsListCard = {
     name: "SsListCard",
     props: {
@@ -4184,13 +4250,23 @@ import { EVEN_VAR } from "./EventBus.js";
     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%";
+      // 移除 itemWidth 计算属性,不再需要 by xu 20260105
+      // 判断卡片类型 by xu 20260105
+      const cardType = Vue.computed(() => {
+        if (!item.thumb) return ''; // 无图
+        // 根据 thumbType 字段判断,如果没有则默认为证件照
+        return item.thumbType === 'thumbnail' ? 'card-thumbnail' : 'card-photo';
+      });
+      // 判断状态类型 - 场地预定状态 by xu 20260105
+      const statusClass = Vue.computed(() => {
+        if (!item.status) return ''; // 无状态,默认白色
+        // 映射状态值到 CSS 类名
+        const statusMap = {
+          'available': 'status-available',
+          'unavailable': 'status-unavailable',
+          'disabled': 'status-disabled'
+        };
+        return statusMap[item.status] || '';
       });
       const onItemClick = (e) => {
         // 清除所有类型卡片的 active 状态
@@ -4213,7 +4289,8 @@ import { EVEN_VAR } from "./EventBus.js";
       };
       return {
         item,
-        itemWidth,
+        cardType,
+        statusClass,
         onItemClick,
         onItemChange,
       };
@@ -4222,24 +4299,59 @@ import { EVEN_VAR } from "./EventBus.js";
     data() {
       return {
         showButtons: false,
+        selected: false, // 选择状态 by xu 20260105
       };
     },
 
+    methods: {
+      // 切换选择状态 by xu 20260105
+      toggleSelect(e) {
+        e.stopPropagation();
+        this.selected = !this.selected;
+        console.log('卡片选中状态:', this.selected);
+      }
+    },
+
     render() {
       const SsCartListIcon = Vue.resolveComponent("ss-cart-list-icon");
+      const SsIcon = Vue.resolveComponent("ss-icon");
       return Vue.h(
           "div",
           {
-            class: { "knowledge-item-container": true, active: this.item.active },
+            class: {
+              "knowledge-item-container": true,
+              active: this.item.active,
+              [this.cardType]: !!this.cardType, // 动态添加卡片类型类名 by xu 20260105
+              [this.statusClass] : !!this.statusClass
+            },
             onClick: this.onItemClick,
-            style: { width: this.itemWidth },
+            // 移除固定宽度,由 CSS min-width 控制 by xu 20260105
           },
           [
+            // 右上角状态图标区域 by xu 20260105
+            this.item?.statusIcons?.length > 0 &&
+            Vue.h(
+                "div",
+                { class: "card-status-icons" },
+                this.item.statusIcons.map((icon) =>
+                    Vue.h(SsIcon, {
+                      class: `status-icon ${icon.class}`,
+                      title: icon.title,
+                    })
+                )
+            ),
+
             this.item?.buttons?.length > 0 &&
             Vue.h(
                 "div",
                 {
                   class: "header",
+                  style: this.item?.statusIcons?.length > 0
+                    ? {
+                        right: `${this.item.statusIcons.length * 48}px`,
+                        borderTopRightRadius: '0'
+                      }
+                    : {},
                   onMouseenter: () => (this.showButtons = true),
                   onMouseleave: () => (this.showButtons = false),
                   onClick: (e) => this.onItemChange(e, this.item.buttons[0], 0),
@@ -4325,6 +4437,15 @@ import { EVEN_VAR } from "./EventBus.js";
                   ]
               ),
             ]),
+
+            // 右下角卡片选择图标 by xu 20260105
+            Vue.h(SsIcon, {
+              class: this.selected ? "card-icon icon-cardChk-on" : "card-icon icon-cardChk",
+              onClick: this.toggleSelect,
+            }),
+
+            // 选中后底部线条 by xu 20260105
+            this.selected && Vue.h("div", { class: "select-bottom-line" }),
           ]
       );
     },
@@ -6608,6 +6729,7 @@ import { EVEN_VAR } from "./EventBus.js";
     app.component("ss-drop-button", SsDropButton);
     app.component("ss-sub-tab", SsSubTab);
     app.component("ss-img", SsImgUpload);
+
     // 设置为中文
     app.use(ElementPlus, {
       locale: ElementPlusLocaleZhCn,

+ 119 - 49
skin/easy/css/base.css

@@ -1806,12 +1806,13 @@ input::placeholder ,textarea::placeholder{
 }
 /* 一级页面搜索结束 */
 
-/* 知识库卡片开始 */
+/* 知识库卡片开始 by xu 20260105 */
 .knowledge-item-container {
-  width: 573px;
-  /* height: 220px; */
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
+  /* width: 573px; 移除固定宽度 by xu 20260105 */
+  min-width: 300px; /* 无图卡片最小宽度 by xu 20260105 */
+  height: 168px;
+  /* box-shadow: 2px 2px 5px #e7e8e8; */
+  background: #ffffff;
   border-radius: 4px;
   position: relative;
   cursor: pointer;
@@ -1820,46 +1821,45 @@ input::placeholder ,textarea::placeholder{
   --header-color: #999;
 }
 
+/* 证件照卡片最小宽度 by xu 20260105 */
+.knowledge-item-container.card-photo {
+  min-width: 320px;
+}
+
+/* 缩略图卡片最小宽度 by xu 20260105 */
+.knowledge-item-container.card-thumbnail {
+  min-width: 400px;
+}
+
+/* 状态颜色 - 场地预定 by xu 20260105 */
+.knowledge-item-container.status-available {
+  background: #d4fad4;
+}
+
+.knowledge-item-container.status-unavailable {
+  background: #fff5c8;
+}
+
+.knowledge-item-container.status-disabled {
+  background: #fadcdc;
+}
+
 .knowledge-item-container:hover {
   --header-display: flex;
-  box-shadow: 8px 8px 0px #3a3e513d;
+  box-shadow: 7px 7px 0px #b6bac3;
 }
 
 .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;
+  box-shadow: 7px 7px 0px #b6bac3;
 }
 .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;
@@ -1900,6 +1900,26 @@ input::placeholder ,textarea::placeholder{
   border-top-right-radius: 4px;
 }
 
+/* 右上角状态图标区域 by xu 20260105 */
+.knowledge-item-container .card-status-icons {
+  position: absolute;
+  top: 0;
+  right: 0;
+  display: flex;
+  flex-direction: row;
+  gap: 0;
+}
+
+.knowledge-item-container .card-status-icons .status-icon {
+  width: 48px;
+  height: 48px;
+  font-size: 24px;
+  font-family: "icon-base" !important;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
 .knowledge-item-container .header:hover {
   --header-color: #fff;
   background: #575d6d;
@@ -1908,25 +1928,31 @@ input::placeholder ,textarea::placeholder{
   color: #ffffff;
 }
 .knowledge-item-container .body {
-  padding: 20px 25px;
+  padding: 22px 20px 8px;
 }
 
 .knowledge-item-container .box-header>div:first-child {
-  color: #333333;
+  color: #000000; /* 修改为纯黑色 by xu 20260105 */
   font-size: 20px;
-  line-height: 2em;
+  line-height: 1em; /* 调整行高 by xu 20260105 */
+  margin-bottom: 16px; /* header 和 body 之间 16px 间距 by xu 20260105 */
 }
 
 .knowledge-item-container .box-body {
   /* height: 140px; */
   color: #333;
-  padding: 10px 0;
+  /* padding: 10px 0; */
   display: flex;
   flex-direction: row;
-  justify-content: space-between;
+  gap: 16px; /* 图片和文字之间 16px 间距 by xu 20260105 */
   align-items: flex-end;
-  --right-padding-left: 20px;
-  --right-width: calc(100% - 86px);
+  --right-padding-left: 0; /* 使用 gap 代替 padding by xu 20260105 */
+  --right-width: calc(100% - 73px - 16px); /* 证件照宽度 73px + 16px 间距 by xu 20260105 */
+}
+
+/* 缩略图卡片的右侧宽度 by xu 20260105 */
+.knowledge-item-container.card-thumbnail .box-body {
+  --right-width: calc(100% - 180px - 16px); /* 缩略图宽度 180px + 16px 间距 by xu 20260105 */
 }
 
 .knowledge-item-container .no-thumb {
@@ -1934,10 +1960,18 @@ input::placeholder ,textarea::placeholder{
   --right-width: 100%;
 }
 
-.knowledge-item-container .left {
-  width: 88px !important;
-  height: 121px !important;
-  border: 1px solid #f6f6f6;
+/* 证件照尺寸,高度100px,宽度按比例73px by xu 20260105 */
+.knowledge-item-container.card-photo .left {
+  width: 73px !important;
+  height: 100px !important;
+  border: 1px solid #dddfe6;
+}
+
+/* 缩略图尺寸固定为 180×100px by xu 20260105 */
+.knowledge-item-container.card-thumbnail .left {
+  width: 180px !important;
+  height: 100px !important;
+  border: 1px solid #dddfe6;
 }
 
 .knowledge-item-container .left>img {
@@ -1951,7 +1985,7 @@ input::placeholder ,textarea::placeholder{
 .knowledge-item-container .right {
   width: var(--right-width);
   padding-left: var(--right-padding-left);
-  padding-top: 5px;
+  /* padding-top: 5px; */
 }
 
 .knowledge-item-container .right .title {
@@ -1967,6 +2001,42 @@ input::placeholder ,textarea::placeholder{
   -webkit-box-orient: vertical;
 }
 
+/* 右下角卡片选择图标 by xu 20260105 */
+.knowledge-item-container .card-icon {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  width: 24px;
+  height: 24px;
+  cursor: pointer;
+  display: none;
+  font-size: 24px;
+  font-family: "icon-base" !important;
+  color: #dddfe6;
+  z-index: 2;
+}
+
+.knowledge-item-container:hover .card-icon {
+  display: block;
+}
+
+.knowledge-item-container .card-icon.icon-cardChk-on {
+  display: block !important;
+  color: #565d6d;
+}
+
+/* 选中后底部线条 by xu 20260105 */
+.knowledge-item-container .select-bottom-line {
+  position: absolute;
+  bottom: -1px;
+  left: 0;
+  width: 100%;
+  height: 4px;
+  background: #565d6d;
+  border-bottom-left-radius: 4px;
+  border-bottom-right-radius: 4px;
+}
+
 .knowledge-item-container  .desc {
   margin-top: 10px;
   font-size: 14px;
@@ -4441,17 +4511,17 @@ input::placeholder ,textarea::placeholder{
 }
 
 .page-container .search-bar {
-  margin-top: 20px;
+  /* margin-top: 20px; */
   width: 100%;
-  height: 40px;
+  height: 60px;
   position: relative;
 }
 
 .page-container .item-content-area {
   height: calc(100% - 75px);
   width: 100%;
-  margin-top: 10px;
-  padding: 10px 0 100px 20px;
+  /* margin-top: 10px; */
+  padding: 0 0 100px 20px;
   display: flex;
   flex-wrap: wrap;
   align-content: flex-start;

+ 74 - 3
skin/easy/css/icon-base/iconfont.css

@@ -5,7 +5,6 @@
        url('../../fonts/icon-base/iconfont.ttf') format('truetype');
 }
 
-
 .icon-base {
   font-family: "icon-base" !important;
   font-size: 16px;
@@ -14,6 +13,78 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-fujian:before {
+  content: "\e668";
+}
+
+.icon-biandongjiaobiao:before {
+  content: "\e664";
+}
+
+.icon-tingyongjiaobiao:before {
+  content: "\e665";
+}
+
+.icon-xinzengjiaobiao:before {
+  content: "\e667";
+}
+
+.icon-cardChk-off:before {
+  content: "\e663";
+}
+
+.icon-spk:before {
+  content: "\e660";
+}
+
+.icon-vid:before {
+  content: "\e661";
+}
+
+.icon-img:before {
+  content: "\e662";
+}
+
+.icon-img-bold:before {
+  content: "\e65f";
+}
+
+.icon-file:before {
+  content: "\e65e";
+}
+
+.icon-vid-bold:before {
+  content: "\e65b";
+}
+
+.icon-aud-bold:before {
+  content: "\e65c";
+}
+
+.icon-txt:before {
+  content: "\e65d";
+}
+
+.icon-cardChk-on:before {
+  content: "\e659";
+}
+
+.icon-cardChk:before {
+  content: "\e65a";
+}
+
+.icon-emoji:before {
+  content: "\e658";
+}
+
+.icon-chk-on:before {
+  content: "\e657";
+}
+
+.icon-chk:before {
+  content: "\e656";
+}
+
 .icon-ptab:before {
   content: "\e655";
 }
@@ -46,7 +117,7 @@
   content: "\e645";
 }
 
-.icon-spk:before {
+.icon-voice:before {
   content: "\e642";
 }
 
@@ -62,7 +133,7 @@
   content: "\e630";
 }
 
-.icon-spk-bold:before {
+.icon-voice-bold:before {
   content: "\e62f";
 }
 

TEMPAT SAMPAH
skin/easy/fonts/icon-base/iconfont.ttf


TEMPAT SAMPAH
skin/easy/fonts/icon-base/iconfont.woff


TEMPAT SAMPAH
skin/easy/fonts/icon-base/iconfont.woff2