From 232225891f27532a550ab9eb50d84f2f07dfac7f Mon Sep 17 00:00:00 2001 From: zxl <763096477@qq.com> Date: 星期一, 16 六月 2025 14:27:11 +0800 Subject: [PATCH] 用户权限管理,url替换后端获取,安装树状结构插件da-tree --- pages/tabbar/user/utils/tool.vue | 31 components/da-tree-vue2/index.vue | 1108 +++++++++++++++++++++++ pages/userPermissions/addStoreMember.vue | 257 ++++- components/da-tree-vue2/utils.js | 151 +++ pages.json | 10 pages/mine/activity/reportActivity.vue | 193 ++-- components/da-tree-vue2/props.js | 183 +++ pages/mine/activity/myActivity.vue | 18 api/userPermissions.js | 54 + pages/mine/activity/detail.vue | 253 +++- package.json | 19 pages/userPermissions/userPermissions.vue | 76 + components/da-tree-vue2/readme.md | 303 ++++++ components/da-tree-vue2/changelog.md | 110 ++ 14 files changed, 2,487 insertions(+), 279 deletions(-) diff --git a/api/userPermissions.js b/api/userPermissions.js index 63e3d92..6e90ea4 100644 --- a/api/userPermissions.js +++ b/api/userPermissions.js @@ -6,6 +6,40 @@ import api from "@/config/api.js"; /** + * 妫�鏌ユ墜鏈哄彿鐮� 杩斿洖涓�涓細鍛樹俊鎭紝濡傛灉鐢佃瘽鍙风爜鍖归厤鍒帮紝鍒欒繑鍥炲凡瀛樺湪鐨勪細鍛� + * @param {Object} param + */ +export function check(param){ + return http.request({ + url:"/lmk/lmk-user-permissions/check", + method: Method.POST, + needToken: true, + data:param + }); +} + +/** + * 鑾峰緱鍟嗗簵瑙掕壊 + */ +export function getStoreRoleList(){ + return http.request({ + url:"/lmk/lmk-user-permissions/getStoreRoleList", + method: Method.GET, + needToken: true, + }) +} +/** + * 鑾峰緱鍟嗗簵閮ㄩ棬鏍戝瀷缁撴瀯 + */ +export function getDeptTree(){ + return http.request({ + url:"/lmk/lmk-user-permissions/store/department", + method: Method.GET, + needToken: true, + }) +} + +/** * 鑾峰緱鐢ㄦ埛鍒楄〃锛堝晢鎴凤級 * @param {Object} param */ @@ -50,7 +84,10 @@ data: param }); } - +/** + * 璇︽儏 + * @param {Object} param + */ export function getDetail(param){ return http.request({ url: "/lmk/lmk-user-permissions/" +param, @@ -59,11 +96,24 @@ }) } - +/** + * 閲嶇疆瀵嗙爜 + * @param {Object} param + */ export function restPassword(param){ return http.request({ url:'/lmk/lmk-user-permissions/restPassword/'+param, method: Method.PUT, needToken: true }) +} +/** + * 鑾峰緱鐧诲綍鐢ㄦ埛鏉冮檺 + */ +export function checkClerkPermission(){ + return http.request({ + url:'/lmk/lmk-user-permissions/checkPermission', + method: Method.GET, + needToken: true + }) } \ No newline at end of file diff --git a/components/da-tree-vue2/changelog.md b/components/da-tree-vue2/changelog.md new file mode 100644 index 0000000..aef338d --- /dev/null +++ b/components/da-tree-vue2/changelog.md @@ -0,0 +1,110 @@ +# 1.4.1 + +## 鐗堟湰璋冩暣 + +寤鸿鏇存柊锛屼絾闇�瑕佹敞鎰忥紝寮傛鏁版嵁鐨勬椂鍊欙紝鍚庡彴闇�杩斿洖 leaf 瀛楁鏉ュ垽鏂槸鍚︽湯椤规暟鎹� + +1. **璋冩暣鏁版嵁椤规牸寮忥紝鏂板 `leaf` 瀛楁锛屾潵鍒ゆ柇鏄惁涓烘湯鑺傜偣** +2. **璋冩暣鏁版嵁椤规牸寮忥紝鏂板 `sort` 瀛楁锛屾潵鎺掑簭鑺傜偣浣嶇疆** +3. **娉ㄦ剰锛氬紓姝ュ姞杞芥暟鎹紝褰撲负鏈」鐨勬椂鍊欙紝闇�瑕佹湇鍔$鏁版嵁杩斿洖 `leaf` 瀛楁** +4. 鏂板 `alwaysFirstLoad` 锛屽嵆寮傛鏁版嵁鎬讳細鍦ㄧ涓�娆″睍寮�鑺傜偣鏃讹紝鎷夊彇涓�娆″悗鍙版暟鎹紝鏉ユ瘮瀵规槸鍚︿竴鑷� +5. 鎷嗗垎 `field` 灞炴�э紝**娉ㄦ剰锛� 1.5.0 鐗堟湰鍚庡皢绉婚櫎 `field` 灞炴��** +6. 鏂板 `labelField` 鍚� `field.label`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**鏍囩**瀛楁锛岄粯璁label` +7. 鏂板 `valueField` 鍚� `field.key`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**鍊�**瀛楁锛岄粯璁value` +8. 鏂板 `childrenField` 鍚� `field.children`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**瀛愭爲鑺傜偣**瀛楁锛岄粯璁children` +9. 鏂板 `disabledField` 鍚� `field.disabled`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**绂佺敤**瀛楁锛岄粯璁disabled` +10. 鏂板 `appendField` 鍚� `field.append`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**鍓爣绛�**瀛楁锛岄粯璁append` +11. 鏂板 `leafField` 鍚� `field.label`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**鏈骇鑺傜偣**瀛楁锛岄粯璁leaf` +12. 鏂板 `sortField` 鍚� `field.label`锛屾寚瀹氳妭鐐瑰璞′腑鏌愪釜灞炴�т负**鎺掑簭**瀛楁锛岄粯璁sort` +13. 鏂板 `isLeafFn` 锛岀敤鏉ヨ嚜瀹氫箟鎺у埗鏁版嵁椤圭殑鏈」 +14. 鏇村鐨勯」鐩ず渚� +15. 鏀寔鍗曢�夊彇娑堥�変腑 +16. 淇鑺傜偣灞曞紑鏃跺彲鑳藉瓨鍦ㄧ殑 bug +17. 淇鑺傜偣閫夋嫨鍙兘瀛樺湪鐨� bug +18. 璋冩暣涓哄瓙鑺傜偣榛樿缁ф壙鐖惰妭鐐圭鐢ㄥ睘鎬� +19. `setExpandedKeys` 娣诲姞鍙傛暟涓�涓� `all` 鍗冲彲鏀寔涓�閿睍寮�/鏀惰捣鍏ㄩ儴鑺傜偣 +20. 鍏跺畠鏇村浼樺寲 + +# 1.3.4 + +浼樺寲 + +1. 浼樺寲鍥炬爣瀛椾綋鍛藉悕 + +# 1.3.3 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.3.2 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.3.1.1 + +淇 + +1. 淇 APP 鍏煎鎬у紩璧风殑鎶ラ敊 + +# 1.3.1 + +## 寤鸿鏇存柊 + +### 1.2.2~1.3.1 鏇存柊棰勮 + +1. 鏂板鏀寔涓婚鎹㈣壊 +2. 鏂板鏀寔鐐瑰嚮鏍囩涔熻兘閫変腑鑺傜偣 +3. 鏂板`field`瀛楁 `append` 鐢ㄤ簬鍦ㄦ爣绛惧悗闈㈡樉绀哄皬鎻愮ず +4. 鏂规硶`setExpandedKeys`鏀寔鍔犺浇鍔ㄦ�佹暟鎹� +5. 鏀寔鍗曢�夌殑`onlyRadioLeaf`涓篳true`鏃跺彲鐐圭埗鑺傜偣灞曞紑/鏀惰捣 +6. 鏂板 `expandChecked`锛屾帶鍒堕�夋嫨鏃舵槸鍚﹀睍寮�褰撳墠宸查�夌殑鎵�鏈変笅绾ц妭鐐� +7. 鏂板 `checkedDisabled`锛屾敮鎸佹覆鏌撶鐢ㄥ�� +8. 鏂板 `packDisabledkey`锛屾敮鎸佽繑鍥炲凡閫変腑鐨勭鐢ㄧ殑 key +9. 鏇村缁嗚妭淇銆佷紭鍖栬绉绘 Vue3 鐗堢殑鏇存柊鏃ュ織 + +鍚庣画鐗堟湰浠嶄笉浼氬疄鏃跺悓姝� Vue3 鐗堟湰锛屽鎬ラ渶鏂板姛鑳斤紝璇风Щ姝� Vue3 鐗� + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.2.2 + +## 寤鸿鏇存柊锛屼紭鍖栬澶氶棶棰� + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.2.1 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.2.0.1 + +浼樺寲 + +1. 浼樺寲灏忕▼搴忓吋瀹� + +# 1.2.0 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.1.1.1 + +淇 + +1. 淇鍚屾鐗堟湰鐨勯敊璇啓娉曞紩璧风殑鎶ラ敊 + +# 1.1.1 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.1.0 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.0.6 + +鏂板 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384&update_log) + +# 1.0.5 + +鐗堟湰鍚屾浜� Vue3 鐗堬紝[鏌ョ湅 Vue3 鐗堟洿鏂版棩蹇梋(https://ext.dcloud.net.cn/plugin?id=12384)锛屽熀浜� Vue2 杩涜寮�鍙戯紝鏀寔鍗曢�夈�佸閫夛紝鍏ㄥ钩鍙板吋瀹广�� diff --git a/components/da-tree-vue2/index.vue b/components/da-tree-vue2/index.vue new file mode 100644 index 0000000..5144cc5 --- /dev/null +++ b/components/da-tree-vue2/index.vue @@ -0,0 +1,1108 @@ +<template> + <view class="da-tree" :style="{'--theme-color': themeColor}"> + <scroll-view class="da-tree-scroll" :scroll-y="true" :scroll-x="false"> + <view + class="da-tree-item" + :class="{'is-show': item.show}" + :style="{paddingLeft: item.level * indent + 'rpx'}" + v-for="item in datalist" + :key="item.key"> + <view + v-if="item.showArrow" + class="da-tree-item__icon" + @click="handleExpandedChange(item)"> + <view :class="['da-tree-item__icon--arr','is-loading']" v-if="loadLoading && item.loading"></view> + <view :class="['da-tree-item__icon--arr','is-expand', {'is-right':!item.expand}]" v-else></view> + </view> + <view v-else class="da-tree-item__icon"></view> + <view + class="da-tree-item__checkbox" + :class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]" + v-if="showCheckbox" + @click="handleCheckChange(item)"> + <view class="da-tree-item__checkbox--icon da-tree-checkbox-checked" v-if="item.checkedStatus === isCheckedStatus"></view> + <view class="da-tree-item__checkbox--icon da-tree-checkbox-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view> + <view class="da-tree-item__checkbox--icon da-tree-checkbox-outline" v-else></view> + </view> + <view + class="da-tree-item__checkbox" + :class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]" + v-if="!showCheckbox && showRadioIcon" + @click="handleRadioChange(item)"> + <view class="da-tree-item__checkbox--icon da-tree-radio-checked" v-if="item.checkedStatus === isCheckedStatus"></view> + <view class="da-tree-item__checkbox--icon da-tree-radio-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view> + <view class="da-tree-item__checkbox--icon da-tree-radio-outline" v-else></view> + </view> + <view class="da-tree-item__label" :class="'da-tree-item__label--'+item.checkedStatus" @click="handleLabelClick(item)">{{ item.label }} <text class="da-tree-item__label--append" v-if="item.append">{{ item.append }}</text></view> + </view> + </scroll-view> + </view> +</template> + +<script> +import { + unCheckedStatus, + halfCheckedStatus, + isCheckedStatus, + deepClone, + getAllNodeKeys, + getAllNodes, + logError, + isArray, + isString, + isNumber, + isFunction, +} from './utils' +import basicProps from './props' + +export default { + name: 'DaTree', + props: basicProps, + data() { + return { + unCheckedStatus, + halfCheckedStatus, + isCheckedStatus, + /** 鍘熷鐨勬爲鏁版嵁 */ + dataRef: [], + /** 澶勭悊鍚庣殑涓�缁存爲椤规暟鎹� */ + datalist: [], + /** 澶勭悊鍚庣殑浠ey涓洪敭鍊肩殑鏍戦」鏁版嵁 */ + datamap: {}, + /** 榛樿鐨勫睍寮�鏁版嵁 */ + expandedKeys: [], + /** 榛樿鐨勫凡閫夋暟鎹� */ + checkedKeys: null, + /** 鍔犺浇鐘舵�� */ + loadLoading: false, + fieldMap: { + value: 'value', + label: 'label', + children: 'children', + disabled: 'disabled', + append: 'append', + leaf: 'leaf', + sort: 'sort', + }, + } + }, + watch: { + defaultExpandedKeys: { + // deep: true, + immediate: true, + handler: function(v) { + if (v?.length) { + this.expandedKeys = v + } else { + this.expandedKeys = [] + } + + // if (v) this.checkInitData(this.datalist) + }, + }, + defaultCheckedKeys: { + // deep: true, + immediate: true, + handler: function(v) { + if (this.showCheckbox) { + if (v?.length) { + this.checkedKeys = v + } else { + this.checkedKeys = [] + } + } else { + if (v || v === 0) { + this.checkedKeys = v + } else { + this.checkedKeys = null + } + } + // this.checkInitData(this.datalist) + }, + }, + data: { + deep: true, + immediate: true, + handler: function(v) { + this.dataRef = deepClone(v) + setTimeout(() => { + this.initData() + }, 36) + }, + }, + }, + methods: { + /** + * 鍒濆鍖栨暟鎹粨鏋� + */ + initData() { + this.fieldMap = { + value: this.field?.key || this.field?.value || this.valueField || 'value', + label: this.field?.label || this.labelField || 'label', + children: this.field?.children || this.childrenField || 'children', + disabled: this.field?.disabled || this.disabledField || 'disabled', + append: this.field?.append || this.appendField || 'append', + leaf: this.field?.leaf || this.leafField || 'leaf', + sort: this.field?.sort || this.sortField || 'sort', + } + + const data = deepClone(this.dataRef) + this.datalist = [] + this.datamap = {} + + // clean tree + this.handleTreeData(data) + // flat tree + this.datalist = this.checkInitData(this.datalist) + + console.log('init datalist', this.datalist) + console.log('init datamap', this.datamap) + }, + + /** + * 杞崲涓鸿妭鐐规暟鎹� + * @param data + * @param parent + * @param level + */ + handleTreeData(data = [], parent = null, level = 0, insertIndex = -1) { + return data.reduce((prev, cur, index) => { + const key = cur[this.fieldMap.value] + const children = cur[this.fieldMap.children] || null + const newItem = this.createNewItem(cur, index, parent, level) + if (insertIndex > -1) { + // 鎻掑叆瀛愰」灏鹃儴 + const index = (parent.childrenKeys?.length || 0) + insertIndex + 1 + if (!parent?.childrenKeys?.includes(key)) { + this.datamap[key] = newItem + this.datalist.splice(index, 0, newItem) + parent.children.push(newItem) + if (newItem.parentKeys?.length) { + newItem.parentKeys.forEach(k => { + this.datamap[k].childrenKeys = [...this.datamap[k].childrenKeys, newItem.key] + }) + } + } + } else { + this.datamap[key] = newItem + this.datalist.push(newItem) + } + + const hasChildren = children && children.length > 0 + if (hasChildren) { + const childrenData = this.handleTreeData(children, newItem, level + 1) + // childrenData.sort((a, b) => a.sort - b.sort) + newItem.children = childrenData + const childrenKeys = childrenData.reduce((p, k) => { + const keys = k.childrenKeys + p.push(...keys, k.key) + return p + }, []) + newItem.childrenKeys = childrenKeys + } + prev.push(newItem) + return prev + }, []) + }, + + /** + * 鍒涘缓鑺傜偣 + * @param item + * @param index + * @param parent + * @param level + */ + createNewItem(item, index, parent, level) { + const key = item[this.fieldMap.value] + const label = item[this.fieldMap.label] + const sort = item[this.fieldMap.sort] || 0 + const children = item[this.fieldMap.children] || null + const append = item[this.fieldMap.append] || null + let disabled = item[this.fieldMap.disabled] || false + // 浼樺厛缁ф壙鐖剁骇绂佺敤灞炴�� + disabled = parent?.disabled || disabled + let isLeaf = isFunction(this.isLeafFn) ? this.isLeafFn(item) : (item[this.fieldMap.leaf] || false) + // const hasChildren = children && children.length > 0 + const isEmptyChildren = children && children.length === 0 + let showArrow = true + // let isLeaf = !hasChildren + let expand = this.defaultExpandAll || false + // 鏄惁寮傛鍔犺浇妯″紡 + const isLoadMode = this.loadMode && isFunction(this.loadApi) + + if (!children) { + expand = false + if (isLoadMode) { + showArrow = true + } else { + isLeaf = true + showArrow = false + } + } + + if (isEmptyChildren) { + expand = false + if (isLoadMode) { + showArrow = true + } else { + isLeaf = true + showArrow = false + } + } + + if (isLeaf) { + showArrow = false + expand = false + } else { + showArrow = true + } + + // onlyRadioLeaf 鍗曢�夊彧鑳介�夋嫨鏈骇鑺傜偣 + if (!this.showCheckbox) { + if (this.onlyRadioLeaf) { + if (!isLeaf) { + disabled = true + } else { + // 浠嶆棫缁ф壙鐖剁被鍘熷绂佺敤鐘舵�� + disabled = parent?.originItem?.disabled || false + } + } + } + + if (disabled) { + if (isLeaf || !children || isEmptyChildren) { + expand = false + showArrow = false + } + } + + const parentKey = parent ? parent.key : null + const show = this.defaultExpandAll || level === 0 + + const newItem = { + key, + parentKey, + label, + append, + isLeaf, + showArrow, + level, + expand, + show, + sort, + disabled, + loaded: false, + loading: false, + indexs: [index], + checkedStatus: unCheckedStatus, + parentKeys: [], + childrenKeys: [], + children: [], + originItem: item, + } + + if (parent) { + newItem.parentKeys = [parent.key, ...parent.parentKeys] + newItem.indexs = [...parent.indexs, index] + } + + return newItem + }, + + /** + * 澶勭悊鍒濆鍖栧唴瀹� + * @param list + */ + checkInitData(list) { + let checkedKeyList = null + let expandedKeyList = [] + if (this.showCheckbox) { + checkedKeyList = [...new Set(this.checkedKeys || [])] + expandedKeyList = this.expandChecked ? ([...(this.checkedKeys || []), ...(this.expandedKeys || [])]) : this.expandedKeys + } else { + checkedKeyList = this.checkedKeys || null + expandedKeyList = this.expandChecked && this.checkedKeys ? ([this.checkedKeys, ...(this.expandedKeys || [])]) : this.expandedKeys + } + + this.handleCheckState(list, checkedKeyList, true) + + // 澶勭悊鍒濆灞曞紑 + expandedKeyList = [...new Set(expandedKeyList)] + if (!this.defaultExpandAll) { + this.handleExpandState(list, expandedKeyList, true) + } + + list.sort((a, b) => { + if (a.sort === 0 && b.sort === 0) { + return 0 + } + + if (a.parentKey === b.parentKey) { + if (a.sort - b.sort > 0) { + return 1 + } else { + return -1 + } + } + + return 0 + }) + + return list + }, + + /** + * 澶勭悊閫変腑 + * @param list + * @param checkedKeyList + */ + handleCheckState(list, checkedKeyList, checked = true) { + // 澶氶�� + if (this.showCheckbox) { + if (checkedKeyList?.length) { + checkedKeyList.forEach(k => { + const item = this.datamap[k] + if (item) { + this.checkTheChecked(item, checked) + } + }) + } + + return + } + + // 鍗曢�� + for (let i = 0; i < list.length; i++) { + const item = list[i] + if (item.key === checkedKeyList) { + // console.log('item.key === checkedKeyList', item.key, checkedKeyList) + this.checkTheRadio(item, checked) + break + } + } + }, + + /** + * 鏍¢獙澶氶�夎妭鐐� + * @param item + * @param checked + */ + checkTheChecked(item, checked = true) { + const { childrenKeys, parentKeys, disabled = false } = item + if (!this.checkedDisabled && disabled) return + + // 褰撳墠 + item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus + + if (!this.checkStrictly) { + // 瀛愮被 + childrenKeys.forEach(k => { + const childrenItem = this.datamap[k] + childrenItem.checkedStatus = (!this.checkedDisabled && childrenItem.disabled) ? childrenItem.checkedStatus : item.checkedStatus + }) + + // 鐖剁被 + parentKeys.forEach(k => { + const parentItem = this.datamap[k] + parentItem.checkedStatus = this.getParentCheckedStatus(parentItem) + }) + } + }, + + /** + * 鏍¢獙鍗曢�夎妭鐐� + * @param item + */ + checkTheRadio(item, checked) { + const { parentKeys, isLeaf, disabled = false } = item + if (!this.checkedDisabled && disabled) return + + // 闄愬埗鏈妭鐐归�変腑锛屼絾褰撳墠闈炴湯鑺傜偣 + if (this.onlyRadioLeaf && !isLeaf) { + logError(`闄愬埗浜嗘湯鑺傜偣閫変腑锛屽綋鍓峓${item.label}]闈炴湯鑺傜偣`) + return + } + + if (this.datalist?.length) { + this.datalist.forEach(k => { + k.checkedStatus = unCheckedStatus + }) + } + console.log('000', item, parentKeys, this.datamap) + + parentKeys.forEach(k => { + console.log('kkk', k, this.datamap[k]) + const parentItem = this.datamap[k] + parentItem.checkedStatus = checked ? this.getParentCheckedStatus(parentItem) : unCheckedStatus + }) + + // 褰撳墠 + item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus + }, + + /** + * 澶勭悊鐖惰妭鐐瑰睍寮� + * @param item + * @param expand + */ + // handleExpandParentNode(item, expand = true) { + // if (!expand) return + + // if (item?.parentKeys?.length) { + // item.parentKeys.forEach(pk => { + // if (!this.datamap[pk].expand) { + // this.datamap[pk].expand = true + // } + // }) + // } + // }, + + /** + * 澶勭悊鑺傜偣灞曞紑 + * @param list + * @param expandedKeyList + * @param expand + */ + handleExpandState(list, expandedKeyList, expand = true) { + // 鏀惰捣 + if (expand === false) { + for (let i = 0; i < list.length; i++) { + const item = list[i] + if (expandedKeyList?.includes(item.key)) { + item.expand = false + if (item.childrenKeys?.length) { + item.childrenKeys.forEach(ck => { + this.datamap[ck].expand = false + this.datamap[ck].show = false + }) + } + } + } + return + } + // 灞曞紑 + for (let i = 0; i < list.length; i++) { + const item = list[i] + // 澶勭悊灞曞紑 + if (expandedKeyList?.includes(item.key)) { + // 鐖跺瓙 + item.expand = true + if (item.children?.length) { + item.children.forEach(k => { + const kItem = this.datamap[k.key] + kItem.show = true + }) + } + + // 鏃忕郴 + if (item.parentKeys?.length) { + item.parentKeys.forEach(k => { + const kItem = this.datamap[k] + kItem.expand = true + if (kItem.children?.length) { + kItem.children.forEach(k => { + const skItem = this.datamap[k.key] + skItem.show = true + }) + } + }) + } + } + } + }, + + /** + * 鐐瑰嚮閫夋 + * @param item + */ + handleCheckChange(item) { + const { childrenKeys, parentKeys, checkedStatus, isLeaf, disabled = false } = item + if (!this.showCheckbox) return + if (disabled) return + + // 褰撳墠 + item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus + + // 瀛愮被 + if (!this.checkStrictly) { + if (this.expandChecked) { + item.show = true + item.expand = childrenKeys?.length > 0 || isLeaf + } + + childrenKeys.forEach(k => { + const childrenItem = this.datamap[k] + childrenItem.checkedStatus = childrenItem.disabled ? childrenItem.checkedStatus : item.checkedStatus + + if (this.expandChecked) { + childrenItem.show = true + childrenItem.expand = childrenItem?.childrenKeys?.length > 0 || childrenItem.isLeaf + } + }) + } else { + if (this.expandChecked) { + logError(`澶氶�夋椂锛屽綋 checkStrictly 涓� true 鏃讹紝涓嶆敮鎸侀�夋嫨鑷姩灞曞紑瀛愯妭鐐瑰睘鎬�(expandChecked)`) + } + } + + // 鐖剁被 + if (!this.checkStrictly) { + parentKeys.forEach(k => { + const parentItem = this.datamap[k] + parentItem.checkedStatus = this.getParentCheckedStatus(parentItem) + }) + } + + const hasCheckedKeys = [] + for (let i = 0; i < this.datalist.length; i++) { + const k = this.datalist[i] + if (k.checkedStatus === isCheckedStatus) { + if ((this.packDisabledkey && k.disabled) || !k.disabled) { + hasCheckedKeys.push(k.key) + } + } + } + + this.checkedKeys = [...hasCheckedKeys] + + this.$emit('change', hasCheckedKeys, item) + }, + + /** + * 鐐瑰嚮鍗曢�� + * @param item + */ + handleRadioChange(item) { + const { parentKeys, checkedStatus, key, disabled = false, isLeaf } = item + if (this.showCheckbox) return + if (this.onlyRadioLeaf && !isLeaf) this.handleExpandedChange(item) + + if (disabled) return + + // 閲嶇疆鎵�鏈夐�夋嫨 + if (this.datalist?.length) { + for (let i = 0; i < this.datalist.length; i++) { + const k = this.datalist[i] + k.checkedStatus = unCheckedStatus + } + } + + parentKeys.forEach(k => { + const parentItem = this.datamap[k] + parentItem.checkedStatus = this.getParentCheckedStatus(parentItem) + }) + + // 褰撳墠 + item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus + + this.checkedKeys = key + this.$emit('change', key, item) + }, + + /** + * 鐐瑰嚮鏍囩 + */ + handleLabelClick(item) { + if (this.showCheckbox) { + this.handleCheckChange(item) + } else { + this.handleRadioChange(item) + } + }, + + /** + * 鐐瑰嚮灞曞紑鏀惰捣 + * @param item + */ + async handleExpandedChange(item) { + const { expand, loading = false, disabled } = item + if (this.loadLoading && loading) return + + this.checkExpandedChange(item) + + // 寮傛 + item.expand = !expand + + let currentItem = null + if (!disabled) { + if (!this.showCheckbox && this.onlyRadioLeaf && this.loadMode) { + logError(`鍗曢�夋椂锛屽綋 onlyRadioLeaf 涓� true 鏃朵笉鏀寔鍔ㄦ�佹暟鎹甡) + } else { + currentItem = await this.loadExpandNode(item) + } + } + + this.$emit('expand', !expand, currentItem || item || null) + }, + + /** + * 妫�鏌ュ睍寮�鐘舵�� + * @param item + */ + checkExpandedChange(item) { + const { expand, childrenKeys, children = null } = item + + if (expand) { + if (childrenKeys?.length) { + childrenKeys.forEach(k => { + if (this.datamap[k]) { + this.datamap[k].show = false + this.datamap[k].expand = false + } + }) + } + } else { + if (children?.length) { + const childrenKeys = children.map(k => k.key) + childrenKeys.forEach(k => { + if (this.datamap[k]) { + this.datamap[k].show = true + } + }) + } + } + }, + + /** + * 鍔犺浇寮傛鏁版嵁 + * @param item + */ + async loadExpandNode(item) { + const { expand, key, loaded, children } = item + if (children?.length && !this.alwaysFirstLoad) { + return item + } + + if (expand && this.loadMode && !loaded) { + if (isFunction(this.loadApi)) { + this.expandedKeys.push(key) + this.loadLoading = true + item.loading = true + + const currentNode = deepClone(item) + const apiRes = await this.loadApi(currentNode) + + // 鏂板瀛愰」 + let newChildren = [...(item.originItem?.children || []), ...(apiRes || [])] + const newChildrenObj = {} + newChildren = newChildren.reduce((total, next) => { + newChildrenObj[next[this.fieldMap]] ? '' : newChildrenObj[next[this.fieldMap]] = true && total.push(next) + return total + }, []) + + item.originItem.children = newChildren || null + if (apiRes?.length) { + const insertIndex = this.datalist.findIndex(k => k.key === item.key) + this.handleTreeData(apiRes, item, item.level + 1, insertIndex) + this.datalist = this.checkInitData(this.datalist) + } else { + // 鍔犺浇鍚庢棤鏁版嵁灏辩Щ闄ゅ睍寮�鍥炬爣 + item.expand = false + item.isLeaf = true + item.showArrow = false + } + + this.loadLoading = false + item.loading = false + item.loaded = true + } + } else { + const eki = this.expandedKeys.findIndex(k => k === key) + if (eki >= 0) { + this.expandedKeys.splice(eki, 1) + } + } + + return item + }, + + /** + * 鑾峰彇鐖剁被鐨勯�変腑鐘舵�� + * @param item + */ + getParentCheckedStatus(item) { + if (!item) { + return unCheckedStatus + } + + if (!this.checkedDisabled && item.disabled) { + return item.checkedStatus || unCheckedStatus + } + + // 鍗曢�夋椂锛岀埗绫绘案杩滀负鍗婇�� + if (!this.showCheckbox) { + return halfCheckedStatus + } + + const { children } = item + // 瀛愮被鍏ㄩ�変腑 + const childrenCheckedAll = children.every(k => k.checkedStatus === isCheckedStatus) + if (childrenCheckedAll) { + return isCheckedStatus + } + + // 瀛愮被鍏ㄤ笉閫変腑 + const childrenUncheckedAll = children.every(k => k.checkedStatus === unCheckedStatus) + if (childrenUncheckedAll) { + return unCheckedStatus + } + + return halfCheckedStatus + }, + /** + * 杩斿洖宸查�夌殑 key + */ + getCheckedKeys() { + return getAllNodeKeys(this.datalist, 'checkedStatus', isCheckedStatus, this.packDisabledkey) + }, + /** + * 鏍规嵁key璁剧疆宸查�� + * @param keys 澶氶�夋椂涓簁ey鐨勬暟缁勶紝鍗曢�夋椂涓簁ey + * @param checked 澶氶�夋椂涓簁ey鐨勬暟缁勶紝鍗曢�夋椂涓簁ey + */ + setCheckedKeys(keys, checked = true) { + // 澶氶�� + if (this.showCheckbox) { + if (!isArray(keys)) { + logError(`setCheckedKeys 绗竴涓弬鏁伴潪鏁扮粍锛屼紶鍏ョ殑鏄痆${keys}]`) + return + } + + const list = this.datalist + + // 鍙栨秷閫夋嫨 + if (checked === false) { + let newCheckedKeys = [] + for (let i = 0; i < this.checkedKeys.length; i++) { + const ck = this.checkedKeys[i] + if (!keys.includes(ck)) { + newCheckedKeys.push(ck) + } + } + newCheckedKeys = [...new Set(newCheckedKeys)] + this.checkedKeys = newCheckedKeys + this.handleCheckState(list, keys, false) + + return + } + + // 閫夋嫨 + const newCheckedKeys = [...this.checkedKeys, ...keys] + this.checkedKeys = [...new Set(newCheckedKeys)] + this.handleCheckState(list, this.checkedKeys, true) + + if (this.expandChecked && checked) { + this.expandedKeys = [...new Set([...(this.checkedKeys || []), ...(keys || [])])] + this.handleExpandState(list, keys, true) + } + return + } + + // 鍗曢�� + // 濡傛灉涓烘暟缁勫垯鎷跨涓�涓� + if (isArray(keys)) { + keys = keys[0] + } + + if (!isString(keys) && !isNumber(keys)) { + logError('setCheckedKeys 绗竴涓弬鏁板瓧绗︿覆鎴栨暟瀛楋紝浼犲叆鐨勬槸==>', keys) + return + } + + const list = this.datalist + this.checkedKeys = checked ? keys : null + + if (this.expandChecked && checked) { + this.handleExpandState(list, [keys], true) + } + + this.handleCheckState(list, keys, !!checked) + }, + /** + * 杩斿洖鍗婇�夌殑 key + */ + getHalfCheckedKeys() { + return getAllNodeKeys(this.datalist, 'checkedStatus', halfCheckedStatus, this.packDisabledkey) + }, + /** + * 杩斿洖鏈�夌殑 key + */ + getUncheckedKeys() { + return getAllNodeKeys(this.datalist, 'checkedStatus', unCheckedStatus, this.packDisabledkey) + }, + /** + * 杩斿洖宸插睍寮�鐨� key + */ + getExpandedKeys() { + return getAllNodeKeys(this.datalist, 'expand', true) + }, + /** + * 鏍规嵁key灞曞紑/鏀惰捣 + * @param keys key鐨勬暟缁勶紝鎴栧瓧绗︿覆 all + * @param expand true涓哄睍寮�/false涓烘敹璧� + */ + setExpandedKeys(keys, expand = true) { + if (!Array.isArray(keys) && keys !== 'all') { + logError('setExpandedKeys 绗竴涓弬鏁伴潪鏁扮粍锛屼紶鍏ョ殑鏄�===>', keys) + return + } + const list = this.datalist + + // 灞曞紑/鏀惰捣鍏ㄩ儴 + if (keys === 'all') { + list.forEach(k => { + k.expand = expand + if (k.level > 0) { + k.show = expand + } + }) + return + } + + // 鏀惰捣 + if (expand === false) { + const newExpandedKeys = [] + for (let i = 0; i < this.expandedKeys.length; i++) { + const ek = this.expandedKeys[i] + if (!keys.includes(ek)) { + newExpandedKeys.push(ek) + } + } + this.expandedKeys = [...new Set(newExpandedKeys)] + this.handleExpandState(list, keys, false) + + return + } + + // 灞曞紑 + const newExpandedKeys = [] + for (let i = 0; i < list.length; i++) { + if (keys.includes(list[i].key)) { + newExpandedKeys.push(list[i].key) + } + } + this.expandedKeys = [...new Set(newExpandedKeys)] + this.handleExpandState(list, newExpandedKeys, true) + }, + /** + * 杩斿洖鏈睍寮�鐨� key + */ + getUnexpandedKeys() { + return getAllNodeKeys(this.datalist, 'expand', false) + }, + /** + * 杩斿洖宸查�夌殑鑺傜偣 + */ + getCheckedNodes() { + return getAllNodes(this.datalist, 'checkedStatus', isCheckedStatus, this.packDisabledkey) + }, + /** + * 杩斿洖鍗婇�夌殑鑺傜偣 + */ + getHalfCheckedNodes() { + return getAllNodes(this.datalist, 'checkedStatus', halfCheckedStatus, this.packDisabledkey) + }, + /** + * 杩斿洖鏈�夌殑鑺傜偣 + */ + getUncheckedNodes() { + return getAllNodes(this.datalist, 'checkedStatus', unCheckedStatus, this.packDisabledkey) + }, + /** + * 杩斿洖宸插睍寮�鐨勮妭鐐� + */ + getExpandedNodes() { + return getAllNodes(this.datalist, 'expand', true) + }, + /** + * 杩斿洖鏈睍寮�鐨勮妭鐐� + */ + getUnexpandedNodes() { + return getAllNodes(this.datalist, 'expand', false) + }, + }, +} +</script> + +<style lang="scss" scoped> +@font-face { + font-family: 'da-tree-iconfont'; /* Project id */ + src: url('data:application/octet-stream;base64,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') format('truetype'); +} + +.da-tree { + width: 100%; + height: 100%; + + &-scroll { + width: 100%; + height: 100%; + } + + &-item { + display: flex; + align-items: center; + height: 0; + padding: 0; + overflow: hidden; + font-size: 28rpx; + line-height: 1; + visibility: hidden; + opacity: 0; + transition: opacity 0.2s linear; + + &.is-show { + height: auto; + padding: 12rpx 24rpx; + visibility: visible; + opacity: 1; + } + + &__icon { + display: flex; + align-items: center; + justify-content: center; + width: 40rpx; + height: 40rpx; + overflow: hidden; + + &--arr { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 32rpx; + height: 32rpx; + + &::after { + position: relative; + z-index: 1; + overflow: hidden; + /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ + font-family: 'da-tree-iconfont' !important; + font-size: 32rpx; + font-style: normal; + color: #999; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + &.is-expand { + &::after { + content: '\e604'; + } + } + + &.is-right { + transform: rotate(-90deg); + } + + &.is-loading { + animation: IconLoading 1s linear 0s infinite; + + &::after { + content: '\e7f1'; + } + } + } + } + + &__checkbox { + width: 40rpx; + height: 40rpx; + overflow: hidden; + + &--left { + order: 0; + } + + &--right { + order: 1; + } + + &--icon { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 40rpx; + height: 40rpx; + + &::after { + position: relative; + top: 0; + left: 0; + z-index: 1; + overflow: hidden; + /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ + font-family: 'da-tree-iconfont' !important; + font-size: 32rpx; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + &.da-tree-checkbox-outline::after { + color: #bbb; + content: '\ead5'; + } + + &.da-tree-checkbox-checked::after { + color: var(--theme-color,#007aff); + content: '\ead4'; + } + + &.da-tree-checkbox-indeterminate::after { + color: var(--theme-color,#007aff); + content: '\ebce'; + } + + &.da-tree-radio-outline::after { + color: #bbb; + content: '\ecc5'; + } + + &.da-tree-radio-checked::after { + color: var(--theme-color,#007aff); + content: '\ecc4'; + } + + &.da-tree-radio-indeterminate::after { + color: var(--theme-color,#007aff); + content: '\ea4f'; + } + } + + &.is--disabled { + cursor: not-allowed; + opacity: 0.35; + } + } + + &__label { + flex: 1; + margin-left: 4rpx; + color: #555; + + &--2 { + color: var(--theme-color,#007aff); + } + + &--append { + font-size: 60%; + opacity: 0.6; + } + } + } +} + +@keyframes IconLoading { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} +</style> diff --git a/components/da-tree-vue2/props.js b/components/da-tree-vue2/props.js new file mode 100644 index 0000000..44c45a0 --- /dev/null +++ b/components/da-tree-vue2/props.js @@ -0,0 +1,183 @@ +// @ts-nocheck +export default { + /** + * 鏍戠殑鏁版嵁 + */ + data: { + type: Array, + default: () => [], + }, + /** + * 涓婚鑹� + */ + themeColor: { + type: String, + default: '#007aff', + }, + /** + * 鏄惁寮�鍚閫夛紝榛樿鍗曢�� + */ + showCheckbox: { + type: Boolean, + default: false, + }, + /** + * 榛樿閫変腑鐨勮妭鐐癸紝娉ㄦ剰鍗曢�夋椂涓哄崟涓猭ey锛屽閫夋椂涓簁ey鐨勬暟缁� + */ + defaultCheckedKeys: { + type: [Array, String, Number], + default: null, + }, + /** + * 閫夋嫨妗嗙殑浣嶇疆锛屽彲閫� left/right + */ + checkboxPlacement: { + type: String, + default: 'left', + }, + /** + * 鏄惁榛樿灞曞紑鍏ㄩ儴 + */ + defaultExpandAll: { + type: Boolean, + default: false, + }, + /** + * 榛樿灞曞紑鐨勮妭鐐� + */ + defaultExpandedKeys: { + type: Array, + default: null, + }, + /** + * 鏄惁鑷姩灞曞紑鍒伴�変腑鐨勮妭鐐癸紝榛樿涓嶅睍寮� + */ + expandChecked: { + type: Boolean, + default: false, + }, + /** + * 瀛愰」缂╄繘璺濈锛岄粯璁�40锛屽崟浣峳px + */ + indent: { + type: Number, + default: 40, + }, + /** + * (鏃�)瀛楁瀵瑰簲鍐呭锛岄粯璁や负 {label: 'label',key: 'key', children: 'children', disabled: 'disabled', append: 'append'} + * 娉ㄦ剰锛�1.5.0鐗堟湰鍚庝笉鍐嶅吋瀹� + */ + field: { + type: Object, + default: null, + }, + /** + * 鏍囩瀛楁(鏂帮紝鎷嗗垎浜�) + */ + labelField: { + type: String, + default: 'label', + }, + /** + * 鍊煎瓧娈�(鏂帮紝鎷嗗垎浜�) + */ + valueField: { + type: String, + default: 'value', + }, + /** + * 涓嬬骇瀛楁(鏂帮紝鎷嗗垎浜�) + */ + childrenField: { + type: String, + default: 'children', + }, + /** + * 绂佺敤瀛楁(鏂帮紝鎷嗗垎浜�) + */ + disabledField: { + type: String, + default: 'disabled', + }, + /** + * 鏈骇鑺傜偣瀛楁(鏂帮紝鎷嗗垎浜�) + */ + leafField: { + type: String, + default: 'leaf', + }, + /** + * 鍓爣绛惧瓧娈�(鏂帮紝鎷嗗垎浜�) + */ + appendField: { + type: String, + default: 'append', + }, + /** + * 鎺掑簭瀛楁(鏂帮紝鎷嗗垎浜�) + */ + sortField: { + type: String, + default: 'sort', + }, + isLeafFn: { + type: Function, + default: null, + }, + /** + * 鏄惁鏄剧ず鍗曢�夊浘鏍囷紝榛樿鏄剧ず + */ + showRadioIcon: { + type: Boolean, + default: true, + }, + /** + * 鍗曢�夋椂鍙厑璁搁�変腑鏈骇锛岄粯璁ゅ彲闅忔剰閫変腑 + */ + onlyRadioLeaf: { + type: Boolean, + default: false, + }, + /** + * 澶氶�夋椂锛屾槸鍚︽墽琛岀埗瀛愪笉鍏宠仈鐨勪换鎰忓嬀閫夛紝榛樿鐖跺瓙鍏宠仈 + */ + checkStrictly: { + type: Boolean, + default: false, + }, + /** + * 涓� true 鏃讹紝绌虹殑 children 鏁扮粍浼氭樉绀哄睍寮�鍥炬爣 + */ + loadMode: { + type: Boolean, + default: false, + }, + /** + * 寮傛鍔犺浇鎺ュ彛 + */ + loadApi: { + type: Function, + default: null, + }, + /** + * 鏄惁鎬诲湪棣栨鐨勬椂鍊欏姞杞戒竴涓嬪唴瀹癸紝鏉ユ瘮瀵规槸鍚︿竴鑷� + */ + alwaysFirstLoad: { + type: Boolean, + default: false, + }, + /** + * 鏄惁娓叉煋(鎿嶄綔)绂佺敤鍊� + */ + checkedDisabled: { + type: Boolean, + default: false, + }, + /** + * 鏄惁杩斿洖宸茬鐢ㄧ殑浣嗗凡閫変腑鐨刱ey + */ + packDisabledkey: { + type: Boolean, + default: true, + }, +} diff --git a/components/da-tree-vue2/readme.md b/components/da-tree-vue2/readme.md new file mode 100644 index 0000000..d4c4459 --- /dev/null +++ b/components/da-tree-vue2/readme.md @@ -0,0 +1,303 @@ +# da-tree-vue2 + +涓�涓熀浜� Vue2 鐨� tree(鏍�)缁勪欢锛屽悓鏃舵敮鎸佷富棰樻崲鑹诧紝鍙兘鏄渶閫傚悎浣犵殑 tree(鏍�)缁勪欢 + +`鍐呭鍚屾浜� Vue3 鐗堟湰锛屽湪姝ゆ煡鐪� ===>` **[Vue3 鐗圿(https://ext.dcloud.net.cn/plugin?id=12384)** + +_涓� Vue3 鐗堟湰鐗堟湰涓嶅悓鐨勬槸锛屾鐗堟湰鍏煎鏇村叏闈紝姣斿 360 灏忕▼搴忋�佸揩搴旂敤绛夊潎鏀寔_ + +### 鍏充簬浣跨敤 + +鍙湪鍙充晶鐨刞浣跨敤 HBuilderX 瀵煎叆鎻掍欢`鎴朻涓嬭浇绀轰緥椤圭洰ZIP`锛屾柟渚垮揩閫熶笂鎵嬨�� + +鍙�氳繃涓嬫柟鐨勭ず渚嬪強鏂囨。璇存槑锛岃繘涓�姝ヤ簡瑙d娇鐢ㄧ粍浠剁浉鍏崇粏鑺傚弬鏁般�� + +鎻掍欢鍦板潃锛歨ttps://ext.dcloud.net.cn/plugin?id=12692 + +### 缁勪欢绀轰緥 + +```jsx +<template> + <view> + <view>澶氶��</view> + <view><button @click="doCheckedTree(['2'],true)">鍏ㄩ��</button></view> + <view><button @click="doCheckedTree(['2'],false)">鍙栨秷鍏ㄩ��</button></view> + <view><button @click="doCheckedTree(['211','222'],true)">閫変腑鎸囧畾鑺傜偣</button></view> + <view><button @click="doCheckedTree(['211','222'],false)">鍙栨秷閫変腑鎸囧畾鑺傜偣</button></view> + <view><button @click="doExpandTree('all',true)">灞曞紑鍏ㄩ儴鑺傜偣</button></view> + <view><button @click="doExpandTree('all',false)">鏀惰捣鍏ㄩ儴鑺傜偣</button></view> + <view><button @click="doExpandTree(['22','23'],true)">灞曞紑鑺傜偣</button></view> + <view><button @click="doExpandTree(['22','23'],false)">鏀惰捣鑺傜偣</button></view> + <DaTreeVue2 + ref="DaTreeRef" + :data="roomTreeData" + labelField="name" + valueField="id" + defaultExpandAll + showCheckbox + :defaultCheckedKeys="defaultCheckedKeysValue" + @change="handleTreeChange" + @expand="handleExpandChange" /> + + <view>鍗曢��</view> + <DaTreeVue2 + :data="roomTreeData" + labelField="name" + valueField="id" + defaultExpandAll + :defaultCheckedKeys="defaultCheckedKeysValue2" + @change="handleTreeChange" + @expand="handleExpandChange" /> + <view>榛樿灞曞紑鎸囧畾鑺傜偣</view> + <DaTreeVue2 + :data="roomTreeData" + labelField="name" + valueField="id" + showCheckbox + :defaultExpandedKeys="defaultExpandKeysValue3" + @change="handleTreeChange" + @expand="handleExpandChange" /> + <view>寮傛鍔犺浇鏁版嵁</view> + <DaTreeVue2 + :data="roomTreeData" + labelField="name" + valueField="id" + showCheckbox + loadMode + :loadApi="GetApiData" + defaultExpandAll + @change="handleTreeChange" + @expand="handleExpandChange" /> + </view> +</template> +``` + +```js +/** + * 妯℃嫙鍒涘缓涓�涓帴鍙f暟鎹� + */ +function GetApiData(currentNode) { + const { key } = currentNode + + return new Promise((resolve) => { + setTimeout(() => { + // 妯℃嫙杩斿洖绌烘暟鎹� + if (key.indexOf('-') > -1) { + return resolve(null) + // return resolve([]) + } + + return resolve([ + { + id: `${key}-1`, + name: `琛屾斂閮╔${key}-1`, + }, + { + id: `${key}-2`, + name: `璐㈠姟閮╔${key}-2`, + append: '瀹氫箟浜嗘湯椤规暟鎹�', + leaf: true, + }, + { + id: `${key}-3`, + name: `璧勬簮閮╔${key}-3`, + }, + { + id: `${key}-4`, + name: `璧勬簮閮╔${key}-3`, + append: '琚鐢紝鏃犲睍寮�鍥炬爣', + disabled: true, + }, + ]) + }, 2000) + }) +} + +import DaTreeVue2 from '@/components/da-tree-vue2/index.vue' +export default { + components: { DaTreeVue2 }, + data() { + return { + GetApiData, + // key鐨勭被鍨嬪繀椤诲搴旀爲鏁版嵁key鐨勭被鍨� + defaultCheckedKeysValue: ['211', '222'], + defaultCheckedKeysValue2: '222', + defaultExpandKeysValue3: ['212', '231'], + roomTreeData: [ + { + id: '2', + name: '琛屾斂涓績', + children: [ + { + id: '21', + name: '琛屾斂閮�', + children: [ + { + id: '211', + name: '琛屾斂涓�閮�', + children: null, + }, + { + id: '212', + name: '琛屾斂浜岄儴', + children: [], + disabled: true, + }, + ], + }, + { + id: '22', + name: '璐㈠姟閮�', + children: [ + { + id: '221', + name: '璐㈠姟涓�閮�', + children: [], + disabled: true, + }, + { + id: '222', + name: '璐㈠姟浜岄儴', + children: [], + }, + ], + }, + { + id: '23', + name: '浜哄姏璧勬簮閮�', + children: [ + { + id: '231', + name: '浜哄姏涓�閮�', + children: [], + }, + { + id: '232', + name: '浜哄姏浜岄儴', + append: '鏇村绀轰緥锛岃涓嬭浇绀轰緥椤圭洰鏌ョ湅', + }, + ], + }, + ], + }, + ], + } + }, + methods: { + doExpandTree(keys, expand) { + this.$refs.DaTreeRef?.setExpandedKeys(keys, expand) + + const gek = this.$refs.DaTreeRef?.getExpandedKeys() + console.log('褰撳墠宸插睍寮�鐨凨EY ==>', gek) + }, + doCheckedTree(keys, checked) { + this.$refs.DaTreeRef?.setCheckedKeys(keys, checked) + + const gek = this.$refs.DaTreeRef?.getCheckedKeys() + console.log('褰撳墠宸查�変腑鐨凨EY ==>', gek) + }, + handleTreeChange(allSelectedKeys, currentItem) { + console.log('handleTreeChange ==>', allSelectedKeys, currentItem) + }, + handleExpandChange(expand, currentItem) { + console.log('handleExpandChange ==>', expand, currentItem) + }, + }, +} +``` + +** 鏇村绀轰緥璇蜂笅杞�/瀵煎叆绀轰緥椤圭洰 ZIP 鏌ョ湅 ** + +### 缁勪欢鍙傛暟 + +| 灞炴�� | 绫诲瀷 | 榛樿鍊� | 蹇呭~ | 璇存槑 | +| :------------------ | :------------------------------ | :--------- | :--- | :--------------------------------------------------------------------------- | +| data | `Array` | - | 鏄� | 鏍戠殑鏁版嵁 | +| themeColor | `String` | `#007aff` | 鍚� | 涓婚鑹诧紝鍗佸叚杩涘埗 | +| defaultCheckedKeys | `Array` \| `Number` \| `String` | - | 鍚� | 榛樿閫変腑鐨勮妭鐐癸紝鍗曢�変负鍗曚釜 key锛屽閫変负 key 鐨勬暟缁� | +| showCheckbox | `Boolean` | `false` | 鍚� | 鏄惁寮�鍚閫夛紝榛樿鍗曢�� | +| checkStrictly | `Boolean` | `false` | 鍚� | 澶氶�夋椂锛屾槸鍚︽墽琛岀埗瀛愪笉鍏宠仈鐨勪换鎰忓嬀閫夛紝榛樿鐖跺瓙鍏宠仈 | +| showRadioIcon | `Boolean` | `true` | 鍚� | 鏄惁鏄剧ず鍗曢�夊浘鏍囷紝榛樿鏄剧ず | +| onlyRadioLeaf | `Boolean` | `true` | 鍚� | 鍗曢�夋椂鍙厑璁搁�変腑鏈骇锛岄粯璁ゅ彲闅忔剰閫変腑 | +| defaultExpandAll | `Boolean` | `false` | 鍚� | 鏄惁榛樿灞曞紑鍏ㄩ儴 | +| defaultExpandedKeys | `Array` | - | 鍚� | 榛樿灞曞紑鐨勮妭鐐� | +| indent | `Number` | `40` | 鍚� | 瀛愰」缂╄繘璺濈锛屽崟浣� rpx | +| checkboxPlacement | `String` | `left` | 鍚� | 閫夋嫨妗嗙殑浣嶇疆锛屽彲閫� left/right | +| loadMode | `Boolean` | `false` | 鍚� | 涓� true 鏃讹紝绌虹殑 children 鏁扮粍浼氭樉绀哄睍寮�鍥炬爣 | +| loadApi | `Function` | - | 鍚� | 閫夋嫨妗嗙殑浣嶇疆锛屽彲閫� left/right | +| checkedDisabled | `Boolean` | `false` | 鍚� | 鏄惁娓叉煋绂佺敤鍊硷紝榛樿涓嶆覆鏌� | +| packDisabledkey | `Boolean` | `true` | 鍚� | 鏄惁杩斿洖宸茬鐢ㄧ殑浣嗗凡閫変腑鐨� key锛岄粯璁よ繑鍥炵鐢ㄥ凡閫夊�� | +| expandChecked | `Boolean` | `false` | 鍚� | 鏄惁鑷姩灞曞紑鍒伴�変腑鐨勮妭鐐癸紝榛樿涓嶅睍寮� | +| alwaysFirstLoad | `Boolean` | `false` | 鍚� | 鏄惁鎬诲湪棣栨鐨勬椂鍊欏姞杞戒竴涓嬪唴瀹癸紝榛樿涓嶅姞杞斤紝鍚﹀垯鍙湁灞曞紑鏈骇鑺傜偣鎵嶄細鍔犺浇鏁版嵁 | +| isLeafFn | `Function` | - | 鍚� | 鑷畾涔夊嚱鏁拌繑鍥炴潵鎺у埗鏁版嵁椤圭殑鏈」 | +| field | `Object` | - | 鍚� | 瀛楁瀵瑰簲鍐呭锛屾牸寮忓弬鑰冧笅鏂�(1.5.0 鍚庣Щ闄わ紝璇风敤鍗曠嫭鐨勫瓧娈靛尮閰�) | +| labelField | `String` | `label` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负鏍囩瀛楁锛岄粯璁label` | +| valueField | `String` | `value` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负鍊煎瓧娈碉紝榛樿`value` | +| childrenField | `String` | `children` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负瀛愭爲鑺傜偣瀛楁锛岄粯璁children` | +| disabledField | `String` | `disabled` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负绂佺敤瀛楁锛岄粯璁disabled` | +| appendField | `String` | `append` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负鍓爣绛惧瓧娈碉紝榛樿`append` | +| leafField | `String` | `leaf` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负鏈骇鑺傜偣瀛楁锛岄粯璁leaf` | +| sortField | `String` | `sort` | 鍚� | 鎸囧畾鑺傜偣瀵硅薄涓煇涓睘鎬т负鎺掑簭瀛楁锛岄粯璁sort` | + +**field 鏍煎紡(1.5.0 鍚庣Щ闄わ紝璇风敤鍗曠嫭鐨勫瓧娈靛尮閰�)** + +```js +{ + label: 'label', + key: 'key', + children: 'children', + disabled: 'disabled', + append: 'append' +} +``` + +### 缁勪欢浜嬩欢 + +| 浜嬩欢鍚嶇О | 鍥炶皟鍙傛暟 | 璇存槑 | +| :------- | :-------------------------------------- | :-------------- | +| change | `(allCheckedKeys, currentItem) => void` | 閫変腑鏃跺洖璋� | +| expand | `(expandState, currentItem) => void` | 灞曞紑/鏀惰捣鏃跺洖璋� | + +### 缁勪欢鏂规硶 + +| 鏂规硶鍚嶇О | 鍙傛暟 | 璇存槑 | +| :------------------ | :--------------- | :------------------------------------------------------------------------------------------------ | +| setCheckedKeys | `(keys,checked)` | 璁剧疆鎸囧畾 key 鐨勮妭鐐归�変腑/鍙栨秷閫変腑鐨勭姸鎬併�傛敞: keys 鍗曢�夋椂涓� key锛屽閫夋椂涓� key 鐨勬暟缁� | +| setExpandedKeys | `(keys,expand)` | 璁剧疆鎸囧畾 key 鐨勮妭鐐瑰睍寮�/鏀惰捣鐨勭姸鎬侊紝褰� keys 涓� all 鏃跺嵆浠h〃灞曞紑/鏀惰捣鍏ㄩ儴銆傛敞锛歬eys 涓烘暟缁勬垨 `all` | +| getCheckedKeys | - | 杩斿洖宸查�夌殑 key | +| getHalfCheckedKeys | - | 杩斿洖鍗婇�夌殑 key | +| getUncheckedKeys | - | 杩斿洖鏈�夌殑 key | +| getCheckedNodes | - | 杩斿洖宸查�夌殑鑺傜偣 | +| getUncheckedNodes | - | 杩斿洖鏈�夌殑鑺傜偣 | +| getHalfCheckedNodes | - | 杩斿洖鍗婇�夌殑鑺傜偣 | +| getExpandedKeys | - | 杩斿洖宸插睍寮�鐨� key | +| getUnexpandedKeys | - | 杩斿洖鏈睍寮�鐨� key | +| getExpandedNodes | - | 杩斿洖宸插睍寮�鐨勮妭鐐� | +| getUnexpandedNodes | - | 杩斿洖鏈睍寮�鐨勮妭鐐� | + +### 缁勪欢鐗堟湰 + +v1.4.1 + +### 宸紓鍖� + +宸查�氳繃娴嬭瘯 + +> - H5 椤甸潰 +> - 寰俊灏忕▼搴� +> - 鏀粯瀹濄�侀拤閽夊皬绋嬪簭 +> - 瀛楄妭璺冲姩銆佹姈闊炽�佷粖鏃ュご鏉″皬绋嬪簭 +> - 鐧惧害灏忕▼搴� +> - 椋炰功灏忕▼搴� +> - QQ 灏忕▼搴� +> - 浜笢灏忕▼搴� +> - 蹇簲鐢� +> - 360 灏忕▼搴� + +鏈祴璇� + +> - 蹇墜灏忕▼搴忕敱浜庨潪浼佷笟鐢ㄦ埛鏆傛棤婕旂ず + +### 寮�鍙戠粍 + +[@CRLANG](https://crlang.com) diff --git a/components/da-tree-vue2/utils.js b/components/da-tree-vue2/utils.js new file mode 100644 index 0000000..979b331 --- /dev/null +++ b/components/da-tree-vue2/utils.js @@ -0,0 +1,151 @@ +// @ts-nocheck +/** 鏈�� */ +export const unCheckedStatus = 0 +/** 鍗婇�� */ +export const halfCheckedStatus = 1 +/** 閫変腑 */ +export const isCheckedStatus = 2 + +/** + * 娣辨嫹璐濆唴瀹� + * @param originData 鎷疯礉瀵硅薄 + * @author crlang(https://crlang.com) + */ +export function deepClone(originData) { + const type = Object.prototype.toString.call(originData) + let data + if (type === '[object Array]') { + data = [] + for (let i = 0; i < originData.length; i++) { + data.push(deepClone(originData[i])) + } + } else if (type === '[object Object]') { + data = {} + for (const prop in originData) { + // eslint-disable-next-line no-prototype-builtins + if (originData.hasOwnProperty(prop)) { // 闈炵户鎵垮睘鎬� + data[prop] = deepClone(originData[prop]) + } + } + } else { + data = originData + } + return data +} + +/** + * 鑾峰彇鎵�鏈夋寚瀹氱殑鑺傜偣 + * @param type + * @param value + * @author crlang(https://crlang.com) + */ +export function getAllNodes(list, type, value, packDisabledkey = true) { + if (!list || list.length === 0) { + return [] + } + + const res = [] + for (let i = 0; i < list.length; i++) { + const item = list[i] + if (item[type] === value) { + if ((packDisabledkey && item.disabled) || !item.disabled) { + res.push(item) + } + } + } + + return res +} + +/** + * 鑾峰彇鎵�鏈夋寚瀹氱殑key鍊� + * @param type + * @param value + * @author crlang(https://crlang.com) + */ +export function getAllNodeKeys(list, type, value, packDisabledkey = true) { + if (!list || list.length === 0) { + return null + } + + const res = [] + for (let i = 0; i < list.length; i++) { + const item = list[i] + if (item[type] === value) { + if ((packDisabledkey && item.disabled) || !item.disabled) { + res.push(item.key) + } + } + } + + return res.length ? res : null +} + +/** + * 閿欒杈撳嚭 + * + * @param msg + */ +export function logError(msg, ...args) { + console.error(`DaTree: ${msg}`, ...args) +} + +const toString = Object.prototype.toString + +export function is(val, type) { + return toString.call(val) === `[object ${type}]` +} + +/** + * 鏄惁瀵硅薄(Object) + * @param val + + */ +export function isObject(val) { + return val !== null && is(val, 'Object') +} + +/** + * 鏄惁鏁板瓧(Number) + * @param val + + */ +export function isNumber(val) { + return is(val, 'Number') +} + +/** + * 鏄惁瀛楃涓�(String) + * @param val + + */ +export function isString(val) { + return is(val, 'String') +} + +/** + * 鏄惁鍑芥暟鏂规硶(Function) + * @param val + + */ +export function isFunction(val) { + return typeof val === 'function' +} + +/** + * 鏄惁甯冨皵(Boolean) + * @param val + + */ +export function isBoolean(val) { + return is(val, 'Boolean') +} + +/** + * 鏄惁鏁扮粍(Array) + * @param val + + */ +export function isArray(val) { + return val && Array.isArray(val) +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c1e9355 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "id": "da-tree-vue2", + "name": "da-tree 鏍戠粍浠讹紙鏀寔鍗曢�夈�佸閫夈�佹棤闄愮骇銆佷富棰樿壊锛孷ue2鐗堬級", + "displayName": "da-tree 鏍戠粍浠讹紙鏀寔鍗曢�夈�佸閫夈�佹棤闄愮骇銆佷富棰樿壊锛孷ue2鐗堬級", + "version": "1.4.1", + "description": "涓�涓熀浜� Vue2 鐨則ree(鏍�)缁勪欢锛屽悓鏃舵敮鎸佷富棰樻崲鑹诧紝鍙兘鏄渶閫傚悎浣犵殑tree(鏍�)缁勪欢", + "keywords": [ + "tree", + "鏍�", + "鏍戠粍浠�", + "da绯诲垪" + ], + "dcloudext": { + "category": [ + "鍓嶇缁勪欢", + "閫氱敤缁勪欢" + ] + } +} \ No newline at end of file diff --git a/pages.json b/pages.json index 5931aad..dc05e07 100644 --- a/pages.json +++ b/pages.json @@ -266,7 +266,8 @@ "u-popup": "view", "u-search": "view", "u-loading": "view", - "u-navbar": "view" + "u-navbar": "view", + "u-loadmore":"view" } } }, @@ -285,7 +286,8 @@ "u-loading": "view", "u-checkbox": "view", "u-checkbox-group": "view", - "u-navbar": "view" + "u-navbar": "view", + "u-loadmore":"view" } } }, @@ -305,7 +307,9 @@ "u-loading": "view", "u-checkbox": "view", "u-checkbox-group": "view", - "u-navbar": "view" + "u-navbar": "view", + "u-loadmore":"view", + "u-switch": "view" } } } diff --git a/pages/mine/activity/detail.vue b/pages/mine/activity/detail.vue index fb61737..6b05c59 100644 --- a/pages/mine/activity/detail.vue +++ b/pages/mine/activity/detail.vue @@ -1,22 +1,21 @@ <template> - <view class="container"> + <view class="container" @touchstart="touchStart" @touchend="touchEnd"> <!-- 椤堕儴娴锋姤鍥� --> <!-- 鍔ㄦ�佸皝闈㈠尯鍩� --> <view class="cover-container"> - <!-- 鍥剧墖绫诲瀷 --> - <block v-if="activityInfo.coverType === '鍥剧墖'"> - <image :src="getUrl(activityInfo.cover)" class="activity-cover" /> - </block> - <block v-if=" activityInfo.coverType === '瑙嗛'"> - <video :src="getUrl(item.cover)" - @play="handleVideoPlay" class="activity-cover"></video> - </block> - <!-- 鏂囧瓧绫诲瀷 --> - <block v-if="activityInfo.coverType === '鏂囧瓧'"> - <view class="text-cover"> - <text class="cover-text">{{ activityInfo.cover }}</text> - </view> - </block> + <!-- 鍥剧墖绫诲瀷 --> + <block v-if="activityInfo.coverType === 'image'"> + <image :src="activityInfo.url" class="activity-cover" /> + </block> + <block v-if=" activityInfo.coverType === 'video'"> + <video :src="activityInfo.url" @play="handleVideoPlay" class="activity-cover"></video> + </block> + <!-- 鏂囧瓧绫诲瀷 --> + <block v-if="activityInfo.coverType === 'text'"> + <view class="text-cover"> + <text class="cover-text">{{ activityInfo.cover }}</text> + </view> + </block> </view> <!-- 娲诲姩鍩烘湰淇℃伅 --> @@ -27,7 +26,7 @@ <text class="time"> 寮�濮嬫椂闂达細{{ activityInfo.startTime }} </text> - + </view> <view> <text class="time"> @@ -49,34 +48,45 @@ </view> </view> - + <!-- 娲诲姩璇︽儏鍐呭 --> - <view class="content-section"> - <rich-text :nodes="activityInfo.activityContent"></rich-text> + <view class="rich-text-container"> + <rich-text :nodes="activityInfo.activityContent" class="rich-text-content"></rich-text> </view> <!-- 鎶ュ悕鐘舵�� --> <view class="status-bar" :style="{ backgroundColor: statusBarColor }"> - <u-button class="signup-btn" @click.stop="activityReport()" :disabled="reportBtn" >{{ reportBtn ? '宸叉姤鍚�': '绔嬪嵆鎶ュ悕'}}</u-button> - <u-button class="signup-btn" @click.stop="collect()">{{ isCollect ? '鍙栨秷鏀惰棌' : '鏀惰棌' }}</u-button> + <u-button class="signup-btn" @click.stop="activityReport()" + :disabled="reportBtn">{{ reportBtn ? '宸叉姤鍚�': '绔嬪嵆鎶ュ悕'}}</u-button> + <view class="collect-icon" @click.stop="collect()"> + <u-icon :name="isCollect ? 'star-fill' : 'star'" size="52" + :color="isCollect ? '#ffcc00' : '#999'"></u-icon> + </view> </view> </view> </template> <script> import UButton from '@/uview-components/uview-ui/components/u-button/u-button.vue'; - import {changeCollect} from '@/api/collect.js' - import {getFilePreviewUrl} from '@/api/common.js' + import UIcon from '@/uview-components/uview-ui/components/u-icon/u-icon.vue'; + import { + changeCollect + } from '@/api/collect.js' + import { + getFilePreviewUrl + } from '@/api/common.js' import { getActivityDetail, activityReport } from '@/api/activity.js'; export default { components: { - UButton + UButton, + UIcon, }, data() { return { + startX: 0, activityInfo: { coverType: '', cover: '', @@ -87,18 +97,19 @@ tags: [], activityContent: '', activityType: '', - limitUserNum:'', + limitUserNum: '', + url: '', }, - isCollect:false, - reportBtn:false, + isCollect: false, + reportBtn: false, detailId: null, // 瀛樺偍鎺ユ敹鐨勫弬鏁� reportFrom: { activityId: '', cancel: false, //鎶ュ悕鎺ュ彛榛樿鎴慺alse }, - collectForm:{ - collectType:'', - refId:'', + collectForm: { + collectType: '', + refId: '', }, }; }, @@ -111,10 +122,36 @@ } }, methods: { - collect(){ + /** + * 瑙︽懜寮�濮� + * @param {Object} e + */ + touchStart(e) { + if (e.touches.length == 1) { + //璁剧疆瑙︽懜璧峰鐐规按骞虫柟鍚戜綅缃� + this.startX = e.touches[0].clientX; + } + }, + + touchEnd(e) { + if (e.changedTouches.length == 1) { + //鎵嬫寚绉诲姩缁撴潫鍚庢按骞充綅缃� + var endX = e.changedTouches[0].clientX; + let diff = endX - this.startX; + if (Math.abs(diff) > 20) { + if (diff > 0) { + console.log("宸︽粦..."); + + } else { + console.log("鍙虫粦..."); + } + } + } + }, + collect() { this.collectForm.collectType = 'activity' this.collectForm.refId = this.detailId - changeCollect(this.collectForm).then(res=>{ + changeCollect(this.collectForm).then(res => { if (res.statusCode === 200) { this.isCollect = true; uni.showToast({ @@ -123,7 +160,9 @@ mask: true // 鏄惁鏄剧ず閫忔槑钂欏眰锛堥槻姝㈣Е鎽哥┛閫忥級 }); } + this.getActivityDetail(this.detailId); }) + }, //鎶ュ悕 activityReport() { @@ -137,13 +176,9 @@ mask: true // 鏄惁鏄剧ず閫忔槑钂欏眰锛堥槻姝㈣Е鎽哥┛閫忥級 }); } - + }) - }, - getUrl(params){ - getFilePreviewUrl(params).then(res =>{ - return res.data.data - }) + }, getActivityDetail(id) { uni.showLoading({ @@ -160,16 +195,16 @@ this.activityInfo.startTime = res.data.data.startTime; this.activityInfo.endTime = res.data.data.endTime; this.activityInfo.activityLocation = res.data.data.activityLocation; - this.activityInfo.activityContent = '<h2>娲诲姩浠嬬粛</h2>' + '<p>' + res.data.data.activityContent + '</p>'; + this.activityInfo.activityContent = '<h2>娲诲姩浠嬬粛</h2>' + res.data.data.activityContent; this.activityInfo.activityType = res.data.data.activityType; this.activityInfo.limitUserNum = res.data.data.limitUserNum; this.reportBtn = res.data.data.isReport; this.isCollect = res.data.data.isCollect; + this.activityInfo.url = res.data.data.url; } }) }, loadDetailData() { - //鑾峰緱璇︽儏鎺ュ彛 this.getActivityDetail(this.detailId); @@ -182,39 +217,41 @@ <style lang="scss"> /* 灏侀潰瀹瑰櫒 */ .cover-container { - position: relative; - width: 100%; - height: 400rpx; - overflow: hidden; - background-color: #f5f5f5; + position: relative; + width: 100%; + height: 400rpx; + overflow: hidden; + background-color: #f5f5f5; } - + /* 鍥剧墖/瑙嗛灏侀潰鏍峰紡 */ .activity-cover { - width: 100%; - height: 100%; - border-radius: 0; /* 涓庡垪琛ㄩ〉淇濇寔涓�鑷� */ + width: 100%; + height: 100%; + border-radius: 0; + /* 涓庡垪琛ㄩ〉淇濇寔涓�鑷� */ } - + /* 鏂囧瓧灏侀潰鏍峰紡 - 涓庡垪琛ㄩ〉淇濇寔涓�鑷� */ .text-cover { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); - padding: 40rpx; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); + padding: 40rpx; } - + .cover-text { - color: #fff; - font-size: 36rpx; - font-weight: bold; - text-align: center; - line-height: 1.4; - text-shadow: 0 2rpx 4rpx rgba(0,0,0,0.2); + color: #fff; + font-size: 36rpx; + font-weight: bold; + text-align: center; + line-height: 1.4; + text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2); } + .header-image { width: 100%; height: 400rpx; @@ -259,27 +296,25 @@ } .status-bar { - padding: 25rpx 30rpx; display: flex; - justify-content: space-between; align-items: center; - color: #fff; - font-size: 28rpx; - margin: 20rpx 0; + padding: 10px 15px; + justify-content: space-between; } .signup-btn { - background: #fff; - color: #2196F3; - padding: 10rpx 30rpx; - border-radius: 50rpx; - font-size: 28rpx; + flex: 1; + margin-right: 15px; } - .content-section { - padding: 30rpx; - background: #fff; - margin-top: 20rpx; + .collect-icon { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background-color: #f5f5f5; + border-radius: 8px; } .footer { @@ -309,10 +344,64 @@ height: 40rpx; margin-bottom: 10rpx; } + .btn-container { - display: flex; - justify-content: center; - align-items: center; - margin-top: 8px; /* 涓庝笂鏂规爣棰樹繚鎸侀棿璺� */ + display: flex; + justify-content: center; + align-items: center; + margin-top: 8px; + /* 涓庝笂鏂规爣棰樹繚鎸侀棿璺� */ + } + + .rich-text-container { + padding: 15px; + } + + .rich-text-content { + line-height: 1.6; + color: #333; + font-size: 16px; + } + + .rich-text-content img { + max-width: 100%; + height: auto; + display: block; + margin: 10px auto; + } + + .rich-text-content video { + max-width: 100%; + height: auto; + display: block; + margin: 10px auto; + } + + .rich-text-content p { + margin-bottom: 10px; + } + + .rich-text-content h1, + .rich-text-content h2, + .rich-text-content h3, + .rich-text-content h4 { + margin: 20px 0 10px; + color: #222; + } + + .rich-text-content h1 { + font-size: 24px; + } + + .rich-text-content h2 { + font-size: 22px; + } + + .rich-text-content h3 { + font-size: 20px; + } + + .rich-text-content h4 { + font-size: 18px; } </style> \ No newline at end of file diff --git a/pages/mine/activity/myActivity.vue b/pages/mine/activity/myActivity.vue index c977479..37f2a2a 100644 --- a/pages/mine/activity/myActivity.vue +++ b/pages/mine/activity/myActivity.vue @@ -27,10 +27,10 @@ > <!-- 灏侀潰鍖哄煙 --> <view class="cover-container"> - <block v-if="item.coverType === '鍥剧墖' || item.coverType === '瑙嗛'"> - <image :src="getUrl(item.cover)" mode="aspectFill" class="activity-cover" /> + <block v-if="item.coverType === 'image' || item.coverType === 'video'"> + <image :src="item.url" mode="aspectFill" class="activity-cover" /> </block> - <block v-if="item.coverType === '鏂囧瓧'"> + <block v-if="item.coverType === 'text'"> <view class="activity-cover text-cover">{{ item.cover }}</view> </block> </view> @@ -80,10 +80,10 @@ class="activity-item card" > <view class="cover-container"> - <block v-if="item.coverType === '鍥剧墖' || item.coverType === '瑙嗛'"> - <image :src="getUrl(item.cover)" mode="aspectFill" class="activity-cover" /> + <block v-if="item.coverType === 'image' || item.coverType === 'video'"> + <image :src="item.url" mode="aspectFill" class="activity-cover" /> </block> - <block v-if="item.coverType === '鏂囧瓧'"> + <block v-if="item.coverType === 'text'"> <view class="activity-cover text-cover">{{ item.cover }}</view> </block> </view> @@ -123,10 +123,10 @@ class="activity-item card" > <view class="cover-container"> - <block v-if="item.coverType === '鍥剧墖' || item.coverType === '瑙嗛'"> - <image :src="getUrl(item.cover)" mode="aspectFill" class="activity-cover" /> + <block v-if="item.coverType === 'image' || item.coverType === 'video'"> + <image :src="item.url" mode="aspectFill" class="activity-cover" /> </block> - <block v-if="item.coverType === '鏂囧瓧'"> + <block v-if="item.coverType === 'text'"> <view class="activity-cover text-cover">{{ item.cover }}</view> </block> </view> diff --git a/pages/mine/activity/reportActivity.vue b/pages/mine/activity/reportActivity.vue index 26f3407..1e9412b 100644 --- a/pages/mine/activity/reportActivity.vue +++ b/pages/mine/activity/reportActivity.vue @@ -1,24 +1,24 @@ <template> <view class="wrapper"> + + + <view style="height: 100rpx"></view> <!-- 鍐呭鍖哄煙 --> - <scroll-view scroll-y class="content" style="height: 100vh;" @scrolltolower="loadMore" - :lower-threshold="100" - > + <scroll-view scroll-y class="content" style="height: 40vh;" @scrolltolower="loadMore" :lower-threshold="100"> <view class="waterfall"> <view class="column" v-for="(column, index) in columns" :key="index"> <!-- 閬嶅巻姣忓垪鍐呭 --> <view class="item" v-for="(item, idx) in column" :key="item.id" @click="handleItemClick(item)"> <!-- 鍥剧墖绫诲瀷 --> - <image v-if="item.type === '鍥剧墖'" :src="getUrl(item.cover)" mode="widthFix" class="media" - @load="imageLoad" :data-item="item" :style="{ height: item.height + 'px' }" /> + <image v-if="item.type === 'image'" :src="item.url" mode="widthFix" class="media" @load="imageLoad" :data-item="item" + :style="{ height: item.height + 'px' }" /> <!-- 瑙嗛绫诲瀷 --> - <video v-if="item.type === '瑙嗛'" :src="getUrl(item.cover)" class="media" controls - :poster="item.poster" @play="handleVideoPlay" - :style="{ height: item.height + 'px' }"></video> + <video v-if="item.type === 'video'" :src="item.url" class="media" controls :poster="item.poster" :data-item="item" + @play="handleVideoPlay" :style="{ height: item.height + 'px' }"></video> <!-- 鏂囧瓧绫诲瀷 --> - <view v-if="item.type === '鏂囧瓧'" class="text-content"> + <view v-if="item.type === 'text'" class="text-content"> <text class="title">{{ item.cover }}</text> </view> <text class="title">{{ item.title }}</text> @@ -26,26 +26,23 @@ </view> </view> </view> - <!-- <view style="height: 150rpx;"></view> --> - <!-- 鏀硅繘鐨勫姞杞芥洿澶氭彁绀� --> - <view class="load-more"> - <u-loadmore - v-if="mockData.length > 0" - :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" - :load-text="{ + <!-- <view style="height: 150rpx;"></view> --> + <!-- 鏀硅繘鐨勫姞杞芥洿澶氭彁绀� --> + <view class="load-more"> + <u-loadmore v-if="mockData.length > 0" :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" + :load-text="{ loadmore: '涓婃媺鍔犺浇鏇村', loading: '姝e湪鍔犺浇', nomore: '娌℃湁鏇村浜�' - }" - /> - </view> - <view style="height:150rpx"> - - </view> + }" /> + </view> + <view style="height:150rpx"> + + </view> </scroll-view> - - + + </view> </template> @@ -81,7 +78,7 @@ baseTextHeight: 120, // 鏂囧瓧鍩虹楂樺害 query: { pageNumber: 1, - pageSize: 8, + pageSize: 10, }, loading: false, // 鏄惁姝e湪鍔犺浇 noMore: false, // 鏄惁娌℃湁鏇村鏁版嵁 @@ -92,12 +89,6 @@ this.getActivityList(); }, methods: { - getUrl(params) { - getFilePreviewUrl(params).then(res => { - return res.data.data - }) - }, - /** * 涓嬫媺鍒锋柊鏃� */ @@ -108,62 +99,63 @@ this.getActivityList(); }, loadMore() { - - // 鏄剧ず鍔犺浇鐘舵�� - this.loading = true; - - // 寤惰繜鎵ц璁︰I鏈夊弽搴旀椂闂� - setTimeout(() => { - this.query.pageNumber += 1; - this.getActivityList(); - }, 300); + + // 鏄剧ず鍔犺浇鐘舵�� + this.loading = true; + + // 寤惰繜鎵ц璁︰I鏈夊弽搴旀椂闂� + setTimeout(() => { + this.query.pageNumber += 1; + this.getActivityList(); + }, 300); }, async getActivityList() { - - try { - - const res = await getActivityReportList(this.query); - this.loading = false; - if (res.statusCode === 200) { - const newData = res.data.data.map(value => ({ - id: value.id, - type: value.coverType, - cover: value.cover, - height: value.coverType === '鍥剧墖' ? this.baseImageHeight : - value.coverType === '瑙嗛' ? this.baseVideoHeight : this.baseTextHeight, - title: value.activityName, - content: value.activityContent, - poster: '', - })); - - // 鏇存柊鎬绘暟鎹噺 - this.total = res.data.total || 0; - - // 杩藉姞鎴栨浛鎹㈡暟鎹� - this.mockData = this.query.pageNumber === 1 - ? newData - : [...this.mockData, ...newData]; - - // 鍒ゆ柇鏄惁杩樻湁鏇村鏁版嵁 - this.noMore = newData.length < this.query.pageSize || - this.mockData.length >= this.total; - - // 甯冨眬鏇存柊 - this.$nextTick(() => { - this.layoutItems(); - }); - } - } catch (error) { - console.error('鍔犺浇澶辫触:', error); - // 澶辫触鏃跺洖閫�椤电爜 - if (this.query.pageNumber > 1) { - this.query.pageNumber -= 1; - } - } finally { - this.loading = false; - uni.hideLoading(); - uni.stopPullDownRefresh(); - } + + try { + + const res = await getActivityReportList(this.query); + this.loading = false; + if (res.statusCode === 200) { + const newData = res.data.data.map(value => ({ + id: value.id, + type: value.coverType, + cover: value.cover, + height: value.coverType === 'image' ? this.baseImageHeight : value.coverType === + 'video' ? this.baseVideoHeight : this.baseTextHeight, + title: value.activityName, + content: value.activityContent, + poster: '', + url: value.url + })); + + // 鏇存柊鎬绘暟鎹噺 + this.total = res.data.total || 0; + + // 杩藉姞鎴栨浛鎹㈡暟鎹� + this.mockData = this.query.pageNumber === 1 ? + newData : + [...this.mockData, ...newData]; + + // 鍒ゆ柇鏄惁杩樻湁鏇村鏁版嵁 + this.noMore = newData.length < this.query.pageSize || + this.mockData.length >= this.total; + + // 甯冨眬鏇存柊 + this.$nextTick(() => { + this.layoutItems(); + }); + } + } catch (error) { + console.error('鍔犺浇澶辫触:', error); + // 澶辫触鏃跺洖閫�椤电爜 + if (this.query.pageNumber > 1) { + this.query.pageNumber -= 1; + } + } finally { + this.loading = false; + uni.hideLoading(); + uni.stopPullDownRefresh(); + } }, // 鍥剧墖鍔犺浇瀹屾垚鍥炶皟 layoutItems() { @@ -188,6 +180,10 @@ const ratio = height / width; const item = e.currentTarget.dataset.item; + if (!item) { + console.error('鏃犳硶鑾峰彇鍥剧墖椤规暟鎹�', e); + return; + } // 閲嶆柊璁$畻瀹為檯鏄剧ず楂樺害 const viewWidth = uni.upx2px(345); // 灏唕px杞崲涓簆x const viewHeight = viewWidth * ratio; @@ -219,13 +215,14 @@ <style lang="scss"> /* 鏂板鍔犺浇鏇村鏍峰紡 */ - .load-more { - padding: 20rpx 0; - text-align: center; - color: #999; - font-size: 26rpx; - background-color: #f7f8fa; - } + .load-more { + padding: 20rpx 0; + text-align: center; + color: #999; + font-size: 26rpx; + background-color: #f7f8fa; + } + .btn-container { display: flex; justify-content: center; @@ -249,12 +246,12 @@ /* 鍐呭鍖哄煙浼樺寲 */ .content { - flex: 1; - overflow: hidden; - padding: 0 20rpx; - box-sizing: border-box; - /* 纭繚鍙互婊氬姩 */ - -webkit-overflow-scrolling: touch; + flex: 1; + overflow: hidden; + padding: 0 20rpx; + box-sizing: border-box; + /* 纭繚鍙互婊氬姩 */ + -webkit-overflow-scrolling: touch; } /* 鐎戝竷娴佸竷灞�浼樺寲 */ diff --git a/pages/tabbar/user/utils/tool.vue b/pages/tabbar/user/utils/tool.vue index 21aa150..3086852 100644 --- a/pages/tabbar/user/utils/tool.vue +++ b/pages/tabbar/user/utils/tool.vue @@ -42,10 +42,10 @@ <view>鎴戠殑鍒嗛攢</view> </view> --> - <view class="interact-item" @click="navigateTo('/pages/mine/myCollect')"> + <!-- <view class="interact-item" @click="navigateTo('/pages/mine/myCollect')"> <image src="/static/mine/shensu.png" mode=""></image> <view>鎴戠殑鏀惰棌</view> - </view> + </view> --> <view class="interact-item" @click="navigateTo('/pages/mine/activity/myActivity')"> <image src="/static/mine/shensu.png" mode=""></image> @@ -62,12 +62,12 @@ <view>鎴戠殑鏀惰棌</view> </view> - <view class="interact-item" @click="navigateTo('/pages/userPermissions/userPermissions')"> + <view class="interact-item" v-if="isStoreManger" @click="navigateTo('/pages/userPermissions/userPermissions')"> <image src="/static/mine/shensu.png" mode=""></image> <view>鐢ㄦ埛鏉冮檺</view> </view> - <view class="interact-item" @click="navigateTo('/pages/customerManager/customerManager')"> + <view class="interact-item" v-if="isStoreManger" @click="navigateTo('/pages/customerManager/customerManager')"> <image src="/static/mine/shensu.png" mode=""></image> <view>瀹㈡埛绠$悊</view> </view> @@ -88,11 +88,6 @@ <image src="/static/mine/sign.png" mode=""></image> <view>姣忔棩绛惧埌</view> </view> - - - - - <view class="interact-item" @click="navigateTo('/pages/cart/coupon/couponCenter')"> <image src="/static/mine/couponcenter.png" mode=""></image> @@ -141,7 +136,8 @@ </template> <script> - import { + import { getUserInfo } from "@/api/members"; +import { distribution } from "@/api/goods"; import configs from "@/config/config"; @@ -150,12 +146,25 @@ export default { data() { return { + isStoreManger:false, configs, storage } }, - + onReady(){ + console.log(123) + getUserInfo().then(res => { + if(res.data.result){ + if(res.data.result.storeId){ + this.isStoreManger = true; + }else{ + this.isStoreManger = false; + } + } + }) + }, methods: { + handleNavigate(url) { uni.navigateTo({ url, diff --git a/pages/userPermissions/addStoreMember.vue b/pages/userPermissions/addStoreMember.vue index 26c68da..dadea27 100644 --- a/pages/userPermissions/addStoreMember.vue +++ b/pages/userPermissions/addStoreMember.vue @@ -3,7 +3,7 @@ <u-navbar :is-back="true" :title="title" title-color="#333" back-icon-color="#333"></u-navbar> <!-- 琛ㄥ崟鍖哄煙 --> <view class="form-card"> - <u-form :model="form" ref="uForm1" label-width="150rpx"> + <u-form :model="form" ref="uForm1" label-width="150rpx" :rules="rules"> <!-- 鐪熷疄濮撳悕 --> <u-form-item label="鐪熷疄濮撳悕" prop="realName" borderBottom required="true"> @@ -19,21 +19,26 @@ <u-input v-model="form.password" placeholder="璇疯緭鍏ュ瘑鐮�" border="none" type="password" /> </u-form-item> - <!-- 瑙掕壊閫夋嫨 --> - <u-form-item label="瑙掕壊" prop="role" borderBottom required="true"> - <!-- 澶嶉�夋缁勶紝澧炲姞甯冨眬鍜岄棿璺� --> + <u-form-item label="瓒呯骇绠$悊鍛�" prop="isSuper" borderBottom required="true"> + <view class="switch-wrapper"> + <u-switch v-model="form.isSuper"></u-switch> + </view> + </u-form-item> + <u-form-item label="瑙掕壊" prop="role" v-if="!form.isSuper"> <u-checkbox-group @change="checkboxGroupChange" class="checkbox-group"> - <u-checkbox @change="checkboxChange" v-model="item.checked" v-for="(item, index) in list" - :key="index" :name="item.name" class="custom-checkbox"> + <u-checkbox @change="checkboxChange" v-model="item.checked" v-for="(item, index) in roleList" + :key="index" :name="item.id" class="custom-checkbox"> <span class="checkbox-label">{{ item.name }}</span> </u-checkbox> - </u-checkbox-group> - <!-- 鍏ㄩ�夋寜閽紝澧炲姞闂磋窛鍜屾牱寮� --> - <!-- <u-button type="text" @click="checkedAll" class="select-all-btn"> - 鍏ㄩ�� - </u-button> --> </u-form-item> + <u-form-item label="鎵�灞為儴闂�" prop="departmentId" borderBottom> + </u-form-item> + <DaTreeVue2 :data="roomTreeData" labelField="name" valueField="id" defaultExpandAll + :defaultCheckedKeys="defaultCheckedKeysValue" @change="handleTreeChange" + @expand="handleExpandChange" /> + <!-- 瑙掕壊閫夋嫨 --> + </u-form> @@ -49,7 +54,10 @@ import { add, update, - getDetail + getDetail, + getStoreRoleList, + getDeptTree, + check } from "@/api/userPermissions.js" import UIcon from '@/uview-components/uview-ui/components/u-icon/u-icon.vue'; import UButton from '@/uview-components/uview-ui/components/u-button/u-button.vue'; @@ -59,11 +67,14 @@ import USearch from '@/uview-components/uview-ui/components/u-search/u-search.vue'; import UPopup from '@/uview-components/uview-ui/components/u-popup/u-popup.vue'; import ULoading from '@/uview-components/uview-ui/components/u-loading/u-loading.vue'; - import UCheckbox from '@/uview-components/uview-ui/components/u-checkbox/u-checkbox.vue'; import UCheckboxGroup from '@/uview-components/uview-ui/components/u-checkbox-group/u-checkbox-group.vue'; + import USwitch from '@/uview-components/uview-ui/components/u-switch/u-switch.vue'; + import DaTreeVue2 from '@/components/da-tree-vue2/index.vue' + export default { + components: { UIcon, UButton, @@ -74,43 +85,70 @@ UPopup, ULoading, UCheckbox, - UCheckboxGroup + UCheckboxGroup, + DaTreeVue2, + USwitch }, data() { return { + checking: false, // 妫�鏌ョ姸鎬� + lastRequest: null, // 鏈�鍚庝竴娆¤姹傜殑鏍囪瘑锛堢敤浜庨槻鎶栵級 + + rules: { + realName: { + required: true, + trigger: ['blur'], + message: '濮撳悕涓嶈兘涓虹┖' + + }, + mobile: [{ + required: true, + trigger: ['blur'], + message: '鐢佃瘽鍙风爜涓嶈兘涓虹┖' + }, + { + pattern: /^1[3-9]\d{9}$/, + message: "鎵嬫満鍙锋牸寮忎笉姝g‘锛堝繀椤绘槸11浣嶄腑鍥藉ぇ闄嗘墜鏈哄彿锛�", + trigger: ["blur"] + }, + { + validator: this.checkPhoneUsage, + trigger: ['blur'] + } + ], + + + password: { + required: true, + trigger: ['blur', 'change'], + message: '瀵嗙爜涓嶈兘涓虹┖' + + }, + }, + defaultCheckedKeysValue: '', title: '', // 琛ㄥ崟鏁版嵁 form: { - id: '', + id: '',//灞炰簬搴楀憳琛╥d mobile: '', realName: '', password: '', - role: '', - oldPassword: '' + role: [], + isSuper: true, + departmentId: '' }, + memberId:'', - role: [], // 鍔犺浇鐘舵�� loading: false, // 瑙掕壊閫夐」 - list: [{ - name: '绠$悊鍛�', - checked: false, - disabled: false - }, - { - name: '绠$悊鍛�2', - checked: false, - disabled: false - }, - { - name: '绠$悊鍛�3', - checked: false, - disabled: false - } - ], - + roleList: [], + roomTreeData: [], }; + }, + onReady() { + //onReady 涓簎ni-app鏀寔鐨勭敓鍛藉懆鏈熶箣涓� + }, onLoad(options) { // 鎺ユ敹 URL 鍙傛暟 @@ -122,8 +160,108 @@ } else { this.title = '鏂板鐢ㄦ埛'; } + this.getRole() + this.getDeptTree() + setTimeout(() => { + this.$refs.uForm1.setRules(this.rules) + }, 500) }, methods: { + // 鑷畾涔夊紓姝ラ獙璇佹柟娉� + checkPhoneUsage(rule, value, callback) { + if (!value || !/^1[3-9]\d{9}$/.test(value)) { + return callback() // 鏍煎紡閿欒鏃惰烦杩囨帴鍙f鏌� + } + + this.checking = true + const currentRequest = Symbol() // 鐢熸垚鍞竴鏍囪瘑 + this.lastRequest = currentRequest + + // 璋冪敤API妫�鏌ユ墜鏈哄彿锛堢ず渚嬩娇鐢╱ni.request锛� + const form ={ + mobile:value, + memberId:this.memberId + } + check(form) + .then(res => { + // 3.1 濡傛灉涓嶆槸鏈�鍚庝竴娆¤姹傦紝蹇界暐缁撴灉 + if (this.lastRequest !== currentRequest) return; + console.log(res) + // 3.2 鏍规嵁涓氬姟閫昏緫鍒ゆ柇鏄惁鍙敤 + if (res.statusCode === 200) { + //鍒ゆ柇鏄惁宸插瓨鍦� + callback(); // 楠岃瘉閫氳繃 + } else { + callback(new Error(res.message || '璇ユ墜鏈哄彿宸茶浣跨敤')); + } + }) + .catch(err => { + // 3.3 缃戠粶閿欒澶勭悊 + callback(new Error('楠岃瘉澶辫触锛岃绋嶅悗閲嶈瘯')); + }) + .finally(() => { + // 3.4 鏃犺鎴愬姛澶辫触閮藉彇娑堝姞杞界姸鎬� + if (this.lastRequest === currentRequest) { + this.checking = false; + } + }); + + }, + change(e) { + console.log('change', e); + }, + //杞崲鏍戠姸缁撴瀯 + renameTitleToName(treeData) { + return treeData.map(item => { + const newItem = { + ...item, + name: item.title // 灏唗itle璧嬪�肩粰name + } + delete newItem.title // 鍒犻櫎鍘焧itle瀛楁 + + if (item.children && item.children.length > 0) { + newItem.children = this.renameTitleToName(item.children) + } + + return newItem + }) + }, + + getDeptTree() { + getDeptTree().then(res => { + if (res.statusCode === 200) { + console.log(res.data.data) + this.roomTreeData = this.renameTitleToName(res.data.data) + } + }) + console.log(this.roomTreeData) + }, + doExpandTree(keys, expand) { + this.$refs.DaTreeRef?.setExpandedKeys(keys, expand) + + const gek = this.$refs.DaTreeRef?.getExpandedKeys() + console.log('褰撳墠宸插睍寮�鐨凨EY ==>', gek) + }, + doCheckedTree(keys, checked) { + this.$refs.DaTreeRef?.setCheckedKeys(keys, checked) + + const gek = this.$refs.DaTreeRef?.getCheckedKeys() + console.log('褰撳墠宸查�変腑鐨凨EY ==>', gek) + }, + handleTreeChange(allSelectedKeys, currentItem) { + console.log('handleTreeChange ==>', allSelectedKeys, currentItem) + this.form.departmentId = allSelectedKeys + }, + handleExpandChange(expand, currentItem) { + console.log('handleExpandChange ==>', expand, currentItem) + }, + getRole() { + getStoreRoleList().then(res => { + if (res.statusCode === 200) { + this.roleList = res.data.data + } + }) + }, //鑾峰緱璇︽儏 getDetail() { uni.showLoading({ @@ -134,29 +272,31 @@ if (res.statusCode === 200) { this.form.mobile = res.data.data.mobile; this.form.realName = res.data.data.realName; - this.form.password = res.data.data.password; + this.form.isSuper = res.data.data.isSuper; + this.defaultCheckedKeysValue = res.data.data.departmentId; + this.memberId = res.data.data.memberId // 瑙f瀽瑙掕壊鏁扮粍 - const roles = JSON.parse(res.data.data.role); + const roles = res.data.data.roleIds.split(','); // 鏇存柊澶嶉�夋閫変腑鐘舵�� - this.list = this.list.map(item => { + this.roleList = this.roleList.map(item => { return { ...item, - checked: roles.includes(item.name) + checked: roles.includes(item.id) }; }); - - this.form.role = roles; } + }) }, // 瑙掕壊閫夋嫨鍙樺寲 checkboxChange(e) { - // console.log(e); + console.log(e); }, checkboxGroupChange(e) { - this.role = e; + console.log(e) + this.form.role = e; }, // 鍏ㄩ�� checkedAll() { @@ -168,14 +308,23 @@ async submitForm() { // 1. 鎵嬪姩瑙﹀彂琛ㄥ崟楠岃瘉 this.$refs.uForm1.validate(valid => { + if (valid) { this.loading = true; // 2. 澶勭悊瑙掕壊鏁版嵁锛堝皢 checked=true 鐨勯」杞负 role 鏁扮粍锛� + const form = { - this.form.role = JSON.stringify(this.role); - console.log(this.form) - if (this.form.id) { - update(this.form).then(res => { + id: this.form.id, + mobile: this.form.mobile, + realName: this.form.realName, + password: this.form.password, + role: this.form.role, + isSuper:this.form.isSuper, + departmentId:this.form.departmentId, + } + + if (form.id) { + update(form).then(res => { this.loading = false; if (res.statusCode === 200) { uni.showToast({ @@ -188,7 +337,7 @@ } }) } else { - add(this.form).then(res => { + add(form).then(res => { this.loading = false; if (res.statusCode === 200) { uni.showToast({ @@ -214,12 +363,14 @@ <style lang="scss" scoped> .checkbox-group { - display: flex; - flex-wrap: wrap; gap: 16px; - /* 閫夐」闂磋窛 */ - margin-bottom: 16px; - /* 涓庢寜閽殑闂磋窛 */ + + } + + .switch-wrapper { + display: flex; + justify-content: flex-start; + width: 100%; } /* 鍗曚釜澶嶉�夋鏍峰紡 */ diff --git a/pages/userPermissions/userPermissions.vue b/pages/userPermissions/userPermissions.vue index c13d57d..7edfdf3 100644 --- a/pages/userPermissions/userPermissions.vue +++ b/pages/userPermissions/userPermissions.vue @@ -6,7 +6,7 @@ </view> <view> - <button class="add-btn" @click="navigateToAdd()">鏂板鐢ㄦ埛</button> + <button class="add-btn" @click="navigateToAdd()" :disabled="!isShopkeeper">鏂板鐢ㄦ埛</button> </view> <!-- 鎼滅储妗� --> <view class="search-box"> @@ -18,16 +18,16 @@ <view class="user-item" v-for="(user, index) in userList" :key="user.id" > <view class="user-info"> - <text class="realName">{{ user.realName }}</text> + <text class="realName">{{ user.realName ? user.realName: '鏈缃汉鍚�' }}</text> <text class="mobile">{{ user.mobile }}</text> </view> <!-- 鎿嶄綔鎸夐挳鍖哄煙 --> <view class="action-buttons"> - <u-button type="primary" size="mini" @click.stop="restPassword(user.memberId)" class="edit-btn">閲嶇疆瀵嗙爜</u-button> - <u-button type="primary" size="mini" @click.stop="navigateToDetail(user.id)" class="edit-btn">淇敼</u-button> - <u-button type="error" size="mini" @click.stop="deleteUser(user.id)" - class="delete-btn">鍒犻櫎</u-button> - </view> + <u-button type="primary" size="mini" @click.stop="restPassword(user.memberId)" class="edit-btn" :disabled="!checkPermission(user)">閲嶇疆瀵嗙爜</u-button> + <u-button type="primary" size="mini" @click.stop="navigateToDetail(user.id)" class="edit-btn" :disabled="!checkPermission(user)">淇敼</u-button> + <u-button type="error" size="mini" @click.stop="deleteUser(user.id)" + class="delete-btn" :disabled="!checkPermission(user)">鍒犻櫎</u-button> + </view> </view> @@ -35,7 +35,7 @@ <view class="load-more"> <u-loadmore - v-if="mockData.length > 0" + v-if="userList.length > 0" :status="loading ? 'loading' : noMore ? 'nomore' : 'loadmore'" :load-text="{ loadmore: '涓婃媺鍔犺浇鏇村', @@ -59,7 +59,8 @@ del, add, update, - restPassword + restPassword, + checkClerkPermission } from "@/api/userPermissions.js" import UIcon from '@/uview-components/uview-ui/components/u-icon/u-icon.vue'; import UButton from '@/uview-components/uview-ui/components/u-button/u-button.vue'; @@ -68,9 +69,14 @@ import UInput from '@/uview-components/uview-ui/components/u-input/u-input.vue'; import USearch from '@/uview-components/uview-ui/components/u-search/u-search.vue'; import UPopup from '@/uview-components/uview-ui/components/u-popup/u-popup.vue'; - import ULoading from '@/uview-components/uview-ui/components/u-loading/u-loading.vue' + import ULoading from '@/uview-components/uview-ui/components/u-loading/u-loading.vue'; + import ULoadmore from '@/uview-components/uview-ui/components/u-loadmore/u-loadmore.vue'; - + import storage from "@/utils/storage.js"; //缂撳瓨 + import { + getUserInfo + } from "@/api/members"; + export default { components: { UIcon, @@ -80,7 +86,8 @@ UInput, USearch, UPopup, - ULoading + ULoading, + ULoadmore, }, data() { return { @@ -89,11 +96,12 @@ noMoreData: false, // 鏄惁娌℃湁鏇村鏁版嵁 query: { realName: '', - page: 1, - pageSize: 10, - } - - + pageNumber: 1, + pageSize: 15, + }, + isSuper:false, + isShopkeeper:false, + clerkId:'',//鐧诲綍璐﹀彿id } }, onShow() { @@ -101,8 +109,31 @@ }, onLoad() { this.getPage() + //鑾峰緱鐢ㄦ埛鏉冮檺 + checkClerkPermission().then(res=>{ + this.isSuper = res.data.data.isSuper; + this.isShopkeeper = res.data.data.isShopkeeper; + this.clerkId = res.data.data.clerkId; + }) + }, + methods: { + //妫�鏌ユ潈闄� + checkPermission(user){ + if(this.isShopkeeper){ + return true; + } + if(this.clerkId === user.id){ + return true; + }else{ + if(this.isSuper && !user.isSuper){ + return true; + } + return false; + } + + }, restPassword(id){ restPassword(id).then(res=>{ if(res.statusCode === 200){ @@ -123,8 +154,9 @@ uni.hideLoading(); if (res.statusCode === 200) { const data = res.data.data; - if (this.query.page === 1) { + if (this.query.pageNumber === 1) { this.userList = data || []; + console.log(this.userList.length) } else { // 鍚﹀垯杩藉姞鏁版嵁 this.userList = [...this.userList, ...(data || [])]; @@ -138,7 +170,7 @@ // 鎼滅储鐢ㄦ埛 searchUser() { - this.query.page = 1 + this.query.pageNumber = 1 this.noMoreData = false this.userList = [] this.getPage() @@ -147,7 +179,7 @@ // 鍔犺浇鏇村 loadMore() { if (!this.noMoreData) { - this.query.page++ + this.query.pageNumber++ this.getPage() } }, @@ -169,7 +201,9 @@ this.getPage(); } }) - } + }, + + } } </script> -- Gitblit v1.8.0