特易招,招聘小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

534 lines
13 KiB

4 months ago
  1. <template>
  2. <!-- #ifdef APP-NVUE -->
  3. <cell :keep-scroll-position="keepScrollPosition">
  4. <!-- #endif -->
  5. <view
  6. :class="{ 'uv-list-item--disabled': disabled }"
  7. :style="[$uv.addStyle(customStyle),{'background-color':customStyle.backgroundColor?customStyle.backgroundColor:'#fff'}]"
  8. :hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uv-list-item--hover'"
  9. class="uv-list-item" @click="onClick">
  10. <view v-if="!isFirstChild" class="border--left" :class="{ 'uv-list--border': border }"></view>
  11. <view class="uv-list-item__wrapper">
  12. <slot>
  13. <view class="uv-list-item__container"
  14. :class="{ 'container--right': showArrow || link, 'flex--direction': directionData === 'column'}"
  15. :style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
  16. <slot name="header">
  17. <view class="uv-list-item__header">
  18. <view v-if="thumb" class="uv-list-item__icon">
  19. <image :src="thumb" class="uv-list-item__icon-img" :class="['uv-list--' + thumbSize]" />
  20. </view>
  21. <view v-else-if="showExtraIcon" class="uv-list-item__icon">
  22. <uv-icon :name="extraIcon.icon" :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" />
  23. </view>
  24. </view>
  25. </slot>
  26. <slot name="body">
  27. <view class="uv-list-item__content"
  28. :class="{ 'uv-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
  29. <text v-if="title" class="uv-list-item__content-title"
  30. :class="[ellipsis && `uv-line-${ellipsis}`]">{{ title }}</text>
  31. <text v-if="note" class="uv-list-item__content-note">{{ note }}</text>
  32. </view>
  33. </slot>
  34. <slot name="footer">
  35. <view v-if="rightText || showBadge || showSwitch" class="uv-list-item__extra"
  36. :class="{ 'flex--justify': directionData === 'column' }">
  37. <text v-if="rightText" class="uv-list-item__extra-text">{{ rightText }}</text>
  38. <uv-badge
  39. v-if="showBadge"
  40. :show="!!(badge.show || badge.isDot || badge.value)"
  41. :isDot="badge.isDot"
  42. :value="badge.value"
  43. :max="badge.max"
  44. :type="badge.type"
  45. :showZero="badge.showZero"
  46. :bgColor="badge.bgColor"
  47. :color="badge.color"
  48. :shape="badge.shape"
  49. :numberType="badge.numberType"
  50. :inverted="badge.inverted"
  51. customStyle="margin-left: 4px;"
  52. ></uv-badge>
  53. <uv-switch v-if="showSwitch" :value="switchChecked" :disabled="disabled" @change="onSwitchChange"></uv-switch>
  54. </view>
  55. </slot>
  56. </view>
  57. </slot>
  58. </view>
  59. <uv-icon v-if="showArrow || link" size="34rpx" class="uv-icon-wrapper" color="#bbb" name="arrow-right" />
  60. </view>
  61. <!-- #ifdef APP-NVUE -->
  62. </cell>
  63. <!-- #endif -->
  64. </template>
  65. <script>
  66. import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
  67. import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
  68. /**
  69. * ListItem 列表子组件
  70. * @description 列表子组件
  71. * @tutorial https://ext.dcloud.net.cn/plugin?id=24
  72. * @property {String} title 标题
  73. * @property {String} note 描述
  74. * @property {String} thumb 左侧缩略图若thumb有值则不会显示扩展图标
  75. * @property {String} thumbSize = [lg|base|sm] 略缩图大小
  76. * @value lg 大图
  77. * @value base 一般
  78. * @value sm 小图
  79. * @property {String} rightText 右侧文字内容
  80. * @property {Boolean} disabled = [true|false] 是否禁用
  81. * @property {Boolean} clickable = [true|false] 是否开启点击反馈
  82. * @property {String} link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
  83. * @value navigateTo uni.navigateTo()
  84. * @value redirectTo uni.redirectTo()
  85. * @value reLaunch uni.reLaunch()
  86. * @value switchTab uni.switchTab()
  87. * @property {String | PageURIString} to 跳转目标页面
  88. * @property {Boolean} showBadge = [true|false] 是否显示数字角标
  89. * @property {Object} badge 扩展数字角标的参数格式为 :badge="{value: 122}"
  90. * @property {Boolean} showSwitch = [true|false] 是否显示Switch
  91. * @property {Boolean} switchChecked = [true|false] Switch是否被选中
  92. * @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
  93. * @property {Object} extraIcon 扩展图标参数格式为 :extraIcon="{icon: 'photo',size: '30px'}"
  94. * @property {String} direction = [row|column] 排版方向
  95. * @value row 水平排列
  96. * @value column 垂直排列
  97. * @event {Function} click 点击 uniListItem 触发事件
  98. * @event {Function} switchChange 点击切换 Switch 时触发
  99. */
  100. export default {
  101. name: 'uv-list-item',
  102. mixins: [mpMixin, mixin],
  103. emits: ['click', 'switchChange'],
  104. props: {
  105. direction: {
  106. type: String,
  107. default: 'row'
  108. },
  109. title: {
  110. type: String,
  111. default: ''
  112. },
  113. note: {
  114. type: String,
  115. default: ''
  116. },
  117. ellipsis: {
  118. type: [Number, String],
  119. default: 0
  120. },
  121. disabled: {
  122. type: [Boolean, String],
  123. default: false
  124. },
  125. clickable: {
  126. type: Boolean,
  127. default: false
  128. },
  129. showArrow: {
  130. type: [Boolean, String],
  131. default: false
  132. },
  133. link: {
  134. type: [Boolean, String],
  135. default: false
  136. },
  137. to: {
  138. type: String,
  139. default: ''
  140. },
  141. showSwitch: {
  142. type: [Boolean, String],
  143. default: false
  144. },
  145. switchChecked: {
  146. type: [Boolean, String],
  147. default: false
  148. },
  149. showBadge: {
  150. type: [Boolean, String],
  151. default: false
  152. },
  153. badge: {
  154. type: Object,
  155. default () {
  156. return {}
  157. }
  158. },
  159. rightText: {
  160. type: String,
  161. default: ''
  162. },
  163. thumb: {
  164. type: String,
  165. default: ''
  166. },
  167. thumbSize: {
  168. type: String,
  169. default: 'base'
  170. },
  171. showExtraIcon: {
  172. type: [Boolean, String],
  173. default: false
  174. },
  175. extraIcon: {
  176. type: Object,
  177. default () {
  178. return {
  179. name: '',
  180. color: '#000000',
  181. size: 20,
  182. customPrefix: ''
  183. };
  184. }
  185. },
  186. border: {
  187. type: Boolean,
  188. default: false
  189. },
  190. customStyle: {
  191. type: Object,
  192. default () {
  193. return {
  194. padding: '',
  195. backgroundColor: '#FFFFFF'
  196. }
  197. }
  198. },
  199. keepScrollPosition: {
  200. type: Boolean,
  201. default: false
  202. }
  203. },
  204. computed: {
  205. directionData(){
  206. return this.direction ? this.direction : (this.parentData.direction ? this.parentData.direction : 'row');
  207. }
  208. },
  209. watch: {
  210. 'customStyle.padding': {
  211. handler(padding) {
  212. if(padding) this.setPadding(padding);
  213. },
  214. immediate: true
  215. }
  216. },
  217. data() {
  218. return {
  219. isFirstChild: false,
  220. padding: {
  221. top: "",
  222. right: "",
  223. bottom: "",
  224. left: ""
  225. },
  226. parentData: {
  227. direction: 'row',
  228. padding: 0
  229. }
  230. };
  231. },
  232. created() {
  233. this.updateParentData();
  234. },
  235. mounted() {
  236. this.init();
  237. this.list = this.getForm()
  238. // 判断是否存在 uv-list 组件
  239. if (this.list) {
  240. if (!this.list.firstChildAppend) {
  241. this.list.firstChildAppend = true;
  242. this.isFirstChild = true;
  243. }
  244. }
  245. },
  246. methods: {
  247. init(){
  248. if (!this.parent) {
  249. this.$uv.error('uv-list-item必须搭配uv-list组件使用');
  250. }
  251. this.$nextTick(()=>{
  252. if(!(this.padding.top || this.padding.right|| this.padding.bottom|| this.padding.left)){
  253. this.setPadding(this.parentData.padding);
  254. }
  255. })
  256. },
  257. updateParentData() {
  258. this.getParentData('uv-list');
  259. },
  260. setPadding(padding){
  261. if(typeof padding == 'number'){
  262. padding += ''
  263. }
  264. let paddingArr = padding.split(' ')
  265. if (paddingArr.length === 1) {
  266. const allPadding = paddingArr[0]
  267. this.padding = {
  268. "top": allPadding,
  269. "right": allPadding,
  270. "bottom": allPadding,
  271. "left": allPadding
  272. }
  273. } else if (paddingArr.length === 2) {
  274. const [verticalPadding, horizontalPadding] = paddingArr;
  275. this.padding = {
  276. "top": verticalPadding,
  277. "right": horizontalPadding,
  278. "bottom": verticalPadding,
  279. "left": horizontalPadding
  280. }
  281. } else if (paddingArr.length === 4) {
  282. const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
  283. this.padding = {
  284. "top": topPadding,
  285. "right": rightPadding,
  286. "bottom": bottomPadding,
  287. "left": leftPadding
  288. }
  289. }
  290. },
  291. /**
  292. * 获取父元素实例
  293. */
  294. getForm(name = 'uniList') {
  295. let parent = this.$parent;
  296. let parentName = parent.$options.name;
  297. while (parentName !== name) {
  298. parent = parent.$parent;
  299. if (!parent) return false
  300. parentName = parent.$options.name;
  301. }
  302. return parent;
  303. },
  304. onClick() {
  305. if (this.to !== '') {
  306. this.openPage();
  307. return;
  308. }
  309. if (this.clickable || this.link) {
  310. this.$emit('click', {
  311. data: {}
  312. });
  313. }
  314. },
  315. onSwitchChange(e) {
  316. this.$emit('switchChange', e);
  317. },
  318. openPage() {
  319. if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
  320. this.pageApi(this.link);
  321. } else {
  322. this.pageApi('navigateTo');
  323. }
  324. },
  325. pageApi(api) {
  326. let callback = {
  327. url: this.to,
  328. success: res => {
  329. this.$emit('click', {
  330. data: res
  331. });
  332. },
  333. fail: err => {
  334. this.$emit('click', {
  335. data: err
  336. });
  337. }
  338. }
  339. switch (api) {
  340. case 'navigateTo':
  341. uni.navigateTo(callback)
  342. break
  343. case 'redirectTo':
  344. uni.redirectTo(callback)
  345. break
  346. case 'reLaunch':
  347. uni.reLaunch(callback)
  348. break
  349. case 'switchTab':
  350. uni.switchTab(callback)
  351. break
  352. default:
  353. uni.navigateTo(callback)
  354. }
  355. }
  356. }
  357. };
  358. </script>
  359. <style lang="scss" scoped>
  360. $show-lines: 1;
  361. @import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
  362. @import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
  363. $uv-font-size-sm:12px;
  364. $uv-font-size-base:14px;
  365. $uv-font-size-lg:16px;
  366. $uv-spacing-col-lg: 12px;
  367. $uv-spacing-row-lg: 15px;
  368. $uv-img-size-sm:20px;
  369. $uv-img-size-base:26px;
  370. $uv-img-size-lg:40px;
  371. $uv-border-color:#e5e5e5;
  372. $uv-bg-color-hover:#f1f1f1;
  373. $uv-text-color-grey:#999;
  374. $list-item-pd: $uv-spacing-col-lg $uv-spacing-row-lg;
  375. .uv-list-item {
  376. @include flex(row);
  377. font-size: $uv-font-size-lg;
  378. position: relative;
  379. justify-content: space-between;
  380. align-items: center;
  381. background-color: #fff;
  382. /* #ifdef H5 */
  383. cursor: pointer;
  384. /* #endif */
  385. }
  386. .uv-list-item--disabled {
  387. opacity: 0.3;
  388. }
  389. .uv-list-item--hover {
  390. background-color: $uv-bg-color-hover !important;
  391. }
  392. .uv-list-item__wrapper {
  393. @include flex(column);
  394. flex: 1;
  395. }
  396. .uv-list-item__container {
  397. position: relative;
  398. @include flex(row);
  399. padding: $list-item-pd;
  400. padding-left: $uv-spacing-row-lg;
  401. flex: 1;
  402. overflow: hidden;
  403. }
  404. .container--right {
  405. padding-right: 0;
  406. }
  407. .uv-list--border {
  408. position: absolute;
  409. top: 0;
  410. right: 0;
  411. left: 0;
  412. /* #ifdef APP-NVUE */
  413. border-top-color: $uv-border-color;
  414. border-top-style: solid;
  415. border-top-width: 0.5px;
  416. /* #endif */
  417. }
  418. /* #ifndef APP-NVUE */
  419. .uv-list--border:after {
  420. position: absolute;
  421. top: 0;
  422. right: 0;
  423. left: 0;
  424. height: 1px;
  425. content: '';
  426. -webkit-transform: scaleY(0.5);
  427. transform: scaleY(0.5);
  428. background-color: $uv-border-color;
  429. }
  430. /* #endif */
  431. .uv-list-item__content {
  432. @include flex(column);
  433. padding-right: 8px;
  434. flex: 1;
  435. color: #3b4144;
  436. justify-content: space-between;
  437. overflow: hidden;
  438. }
  439. .uv-list-item__content--center {
  440. justify-content: center;
  441. }
  442. .uv-list-item__content-title {
  443. font-size: $uv-font-size-base;
  444. color: #3b4144;
  445. overflow: hidden;
  446. }
  447. .uv-list-item__content-note {
  448. margin-top: 6rpx;
  449. color: $uv-text-color-grey;
  450. font-size: $uv-font-size-sm;
  451. overflow: hidden;
  452. }
  453. .uv-list-item__extra {
  454. @include flex(row);
  455. justify-content: flex-end;
  456. align-items: center;
  457. }
  458. .uv-list-item__header {
  459. @include flex(row);
  460. align-items: center;
  461. }
  462. .uv-list-item__icon {
  463. margin-right: 18rpx;
  464. flex-direction: row;
  465. justify-content: center;
  466. align-items: center;
  467. }
  468. .uv-list-item__icon-img {
  469. /* #ifndef APP-NVUE */
  470. display: block;
  471. /* #endif */
  472. height: $uv-img-size-base;
  473. width: $uv-img-size-base;
  474. margin-right: 10px;
  475. }
  476. .uv-icon-wrapper {
  477. /* #ifndef APP-NVUE */
  478. display: flex;
  479. /* #endif */
  480. align-items: center;
  481. padding: 0 10px;
  482. }
  483. .flex--direction {
  484. flex-direction: column;
  485. /* #ifndef APP-NVUE */
  486. align-items: initial;
  487. /* #endif */
  488. }
  489. .flex--justify {
  490. /* #ifndef APP-NVUE */
  491. justify-content: initial;
  492. /* #endif */
  493. }
  494. .uv-list--lg {
  495. height: $uv-img-size-lg;
  496. width: $uv-img-size-lg;
  497. }
  498. .uv-list--base {
  499. height: $uv-img-size-base;
  500. width: $uv-img-size-base;
  501. }
  502. .uv-list--sm {
  503. height: $uv-img-size-sm;
  504. width: $uv-img-size-sm;
  505. }
  506. .uv-list-item__extra-text {
  507. color: $uv-text-color-grey;
  508. font-size: $uv-font-size-sm;
  509. }
  510. </style>