Browse Source

feat: 新增ui组件

cuiyalong 1 year ago
parent
commit
2461e2dbd9

+ 123 - 0
apps/mobile/src/ui/customer-cell/index.vue

@@ -0,0 +1,123 @@
+<template>
+  <div
+    class="customer-cell cell-clickable"
+    :class="{ visited: visited }"
+    @click="$emit('click', $event)"
+  >
+    <div class="customer-hd">
+      <icon name="mine_company" color="#2cb7ca"></icon>
+    </div>
+    <div class="customer-bd">
+      <div class="customer-name" :class="{ 'van-ellipsis': ellipsis }">
+        {{ name }}
+      </div>
+      <div class="cell-info-list">
+        <span
+          class="cell-info-item"
+          v-for="(item, index) in subInfoList"
+          :key="index"
+        >
+          <span class="info-label">{{ item.label }}:</span>
+          <span class="info-value">{{ item.value }}</span>
+        </span>
+      </div>
+      <div class="cell-info-list customer-location">
+        <span class="cell-info-item">
+          <span class="info-label">所在地:</span>
+          <span class="info-value highlight-text">{{ location }}</span>
+        </span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Icon from '@/ui/icon/'
+export default {
+  name: 'CustomerCell',
+  components: {
+    Icon
+  },
+  props: {
+    name: {
+      type: String,
+      default: ''
+    },
+    ellipsis: {
+      type: Boolean,
+      default: false
+    },
+    visited: {
+      type: Boolean,
+      default: false
+    },
+    location: {
+      type: String,
+      default: ''
+    },
+    subInfoList: {
+      type: Array,
+      default() {
+        return [
+          // {
+          //   label: '项目数量',
+          //   value: '8248'
+          // },
+          // {
+          //   label: '项目总金额',
+          //   value: '24.07亿元'
+          // }
+        ]
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.customer-cell {
+  display: flex;
+  padding: 14px 16px;
+  background-color: #fff;
+  &.visited {
+    .customer-name,
+    .cell-info-list {
+      color: $gray_5;
+    }
+  }
+  .customer-hd {
+    .iconfont {
+      font-size: 24px;
+    }
+  }
+  .customer-bd {
+    margin-left: 4px;
+    flex: 1;
+  }
+  .customer-name {
+    font-size: 14px;
+    line-height: 22px;
+    color: $gray_9;
+    &.van-ellipsis {
+      max-width: 300px;
+    }
+  }
+  .cell-info-list {
+    margin-top: 4px;
+    font-size: 12px;
+    line-height: 18px;
+    color: #5f5e64;
+  }
+  .customer-location {
+    font-size: 11px;
+    line-height: 18px;
+    color: #9b9ca3;
+  }
+
+  .cell-info-item {
+    &:not(:last-of-type) {
+      margin-right: 16px;
+    }
+  }
+}
+</style>

+ 4 - 0
apps/mobile/src/ui/index.js

@@ -12,6 +12,8 @@ import BuyerCell from '@/ui/buyer-cell'
 import DropFilter from '@/ui/drop-filter'
 import NoticeBar from '@/ui/notice-bar'
 import JStepper from '@/ui/j-stepper'
+import TimeLine from '@/ui/time-line'
+import CustomerCell from '@/ui/customer-cell'
 
 export {
   AppIcon,
@@ -27,5 +29,7 @@ export {
   CheckBox,
   CheckboxGroup,
   KeepLabel,
+  TimeLine,
+  CustomerCell,
   DropFilter
 }

+ 251 - 0
apps/mobile/src/ui/time-line/index.vue

@@ -0,0 +1,251 @@
+<template>
+  <div class="j-steps">
+    <div
+      class="j-step step-line"
+      :class="[lineTheme, newTag ? '' : 'through']"
+      v-for="(item, index) in stepList"
+      :key="index"
+    >
+      <div class="step-items clickable" @click="linkTo(item)">
+        <div
+          class="step-item step-circle"
+          :data-tip="index === 0 ? newTagText : ''"
+          :class="{
+            text: index === 0 && newTag
+          }"
+        >
+          <slot name="tag-item" :step="item">
+            <div class="tag-list">
+              <span
+                class="step-tag j-tag-item border main round"
+                v-for="(tag, index) in item.tags"
+                :key="index"
+                >{{ tag }}</span
+              >
+              <span class="step-tag item-time">{{ item.step_time }}</span>
+              <span
+                class="step-tag j-tag-item red round"
+                v-if="markedSameId === item.id"
+              >
+                当前信息
+              </span>
+            </div>
+            <span
+              class="step-tag j-tag-item border round"
+              v-if="item.step_bidamount"
+            >
+              {{ item.step_bidamount }}
+            </span>
+          </slot>
+        </div>
+        <div class="step-item">
+          <span class="item-label" v-html="item.content"></span>
+        </div>
+        <div class="step-item step-footer">
+          <slot name="step-footer" :step="item">
+            <span class="step-tag item-time">{{ item.step_time }}</span>
+          </slot>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'time-line',
+  props: {
+    lineTheme: {
+      type: String,
+      default: '',
+      validator(value) {
+        return ['', 'grey'].includes(value)
+      }
+    },
+    newTag: {
+      type: Boolean,
+      default: false
+    },
+    newTagText: {
+      type: String,
+      default: '最新'
+    },
+    // 信息id,当此id与列表信息id匹配时,会显示<当前信息>tag
+    markedSameId: {
+      type: String,
+      default: '225'
+    },
+    stepList: {
+      type: Array,
+      default() {
+        return [
+          // {
+          //   id: '226',
+          //   time: '2024-02-26',
+          //   bidamount: 11,
+          //   tags: [111],
+          //   content: '226-内容内容内容内容内容内容'
+          // },
+          // {
+          //   id: '225',
+          //   time: '2024-02-25',
+          //   tags: [111, 222, 333],
+          //   content: '225-内容内容内容内容内容内容'
+          // },
+          // {
+          //   id: '224',
+          //   time: '2024-02-24',
+          //   tags: [111, 222, 333],
+          //   content: '224-内容内容内容内容内容内容'
+          // }
+        ]
+      }
+    }
+  },
+  methods: {
+    linkTo(item) {
+      this.$emit('itemClick', item)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.j-steps {
+  padding-left: 20px;
+  overflow: hidden;
+}
+
+// .j-tag-item {
+//   $blue: #05a6f3;
+//   display: flex;
+//   align-items: center;
+//   justify-content: center;
+//   padding: 3px 6px;
+//   font-size: 12px;
+//   height: 22px;
+//   color: #5f5e64;
+//   background-color: #f7f9fa;
+//   &.border {
+//     border: 1px solid rgba(0, 0, 0, 0.05);
+//   }
+//   &.main {
+//     color: $main;
+//     border-color: $main;
+//     background-color: rgba($main, 0.1);
+//   }
+//   &.red {
+//     color: $red;
+//     border-color: $red;
+//     background-color: rgba($red, 0.1);
+//   }
+//   &.orange {
+//     color: $orange;
+//     border-color: $orange;
+//     background-color: rgba($orange, 0.1);
+//   }
+//   &.blue {
+//     color: $blue;
+//     border-color: $blue;
+//     background-color: rgba($blue, 0.1);
+//   }
+//   &.round {
+//     border-radius: 4px;
+//   }
+// }
+
+.step-tag-main {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 22px;
+  padding: 0 6px;
+  color: $color_main;
+  font-size: 12px;
+  line-height: 20px;
+  border: 1px solid $color_main;
+  border-radius: 5px;
+}
+.step-line {
+  position: relative;
+  &::before {
+    content: '';
+    position: absolute;
+    top: 20px;
+    left: 2px;
+    width: 1px;
+    height: 100%;
+    background-color: #2abed1;
+    transform: translate(50%, 0);
+  }
+  &.through {
+    &::before {
+      content: '';
+      top: 0;
+    }
+  }
+  &.grey {
+    &::before {
+      background-color: #ececec;
+    }
+  }
+}
+.step-circle {
+  position: relative;
+  &.text {
+    &::before {
+      @extend .step-tag-main;
+      content: attr(data-tip);
+      left: -44px;
+      width: unset;
+      color: #fff;
+      border: 1px solid $color_main;
+    }
+  }
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: -30px;
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    transform: translate(0, -50%);
+    background-color: $color_main;
+    border: 2px solid #d2f6fc;
+  }
+}
+
+.j-step {
+  display: flex;
+  justify-content: space-between;
+  padding: 12px 0;
+  .step-items {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    padding-left: 26px;
+    padding-right: 12px;
+    .step-item {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      font-size: 16px;
+      &:first-of-type {
+        margin-bottom: 10px;
+      }
+    }
+    .tag-list {
+      display: flex;
+    }
+    .step-tag {
+      margin-right: 8px;
+    }
+    .item-time {
+      color: #999;
+      font-size: 14px;
+      line-height: 24px;
+    }
+  }
+}
+</style>