index.tsx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. import "./index.css";
  2. import {
  3. unref,
  4. computed,
  5. nextTick,
  6. onBeforeMount,
  7. defineComponent,
  8. getCurrentInstance
  9. } from "vue";
  10. import { addClass, removeClass, toggleClass } from "@pureadmin/utils";
  11. const stayClass = "stay"; //鼠标点击
  12. const activeClass = "hs-on"; //鼠标移动上去
  13. const voidClass = "hs-off"; //鼠标移开
  14. const inRange = "hs-range"; //当前选中的两个元素之间的背景
  15. const bothLeftSides = "both-left-sides";
  16. const bothRightSides = "both-right-sides";
  17. let selectedDirection = "right"; //默认从左往右,索引变大
  18. let overList = [];
  19. // 存放第一个选中的元素和最后一个选中元素,只能存放这两个元素
  20. let selectedList = [];
  21. const props = {
  22. HsKey: {
  23. type: Number || String,
  24. default: 0
  25. },
  26. disabled: {
  27. type: Boolean,
  28. default: false
  29. },
  30. value: {
  31. type: Number,
  32. default: 0
  33. },
  34. max: {
  35. type: Array,
  36. default() {
  37. return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  38. }
  39. },
  40. // 回显数据的索引,长度必须是2
  41. echo: {
  42. type: Array,
  43. default() {
  44. return [];
  45. }
  46. }
  47. };
  48. export default defineComponent({
  49. name: "ReSelector",
  50. props,
  51. emits: ["selectedVal"],
  52. setup(props, { emit }) {
  53. const instance = getCurrentInstance();
  54. const currentValue = props.value;
  55. const rateDisabled = computed(() => {
  56. return props.disabled;
  57. });
  58. const classes = computed(() => {
  59. const result = [];
  60. let i = 0;
  61. let threshold = currentValue;
  62. if (currentValue !== Math.floor(currentValue)) {
  63. threshold--;
  64. }
  65. for (; i < threshold; i++) {
  66. result.push(activeClass);
  67. }
  68. for (; i < props.max.length; i++) {
  69. result.push(voidClass);
  70. }
  71. return result;
  72. });
  73. // 鼠标移入
  74. const setCurrentValue = index => {
  75. if (props.disabled) return;
  76. // 当选中一个元素后,开始添加背景色
  77. if (selectedList.length === 1) {
  78. if (overList.length < 1) overList.push({ index });
  79. let firstIndex = overList[0].index;
  80. // 往右走,索引变大
  81. if (index > firstIndex) {
  82. selectedDirection = "right";
  83. toggleClass(
  84. false,
  85. bothRightSides,
  86. document.querySelector(".hs-select__item" + selectedList[0].index)
  87. );
  88. while (index >= firstIndex) {
  89. addClass(
  90. document.querySelector(".hs-select__item" + firstIndex),
  91. inRange
  92. );
  93. firstIndex++;
  94. }
  95. } else {
  96. selectedDirection = "left";
  97. toggleClass(
  98. true,
  99. bothRightSides,
  100. document.querySelector(".hs-select__item" + selectedList[0].index)
  101. );
  102. while (index <= firstIndex) {
  103. addClass(
  104. document.querySelector(".hs-select__item" + firstIndex),
  105. inRange
  106. );
  107. firstIndex--;
  108. }
  109. }
  110. }
  111. addClass(document.querySelector("." + voidClass + index), activeClass);
  112. };
  113. // 鼠标离开
  114. const resetCurrentValue = index => {
  115. if (props.disabled) return;
  116. // 移除先检查是否选中 选中则返回false 不移除
  117. const currentHsDom = document.querySelector("." + voidClass + index);
  118. if (currentHsDom.className.includes(stayClass)) {
  119. return false;
  120. } else {
  121. removeClass(currentHsDom, activeClass);
  122. }
  123. // 当选中一个元素后,开始移除背景色
  124. if (selectedList.length === 1) {
  125. const firstIndex = overList[0].index;
  126. if (index >= firstIndex) {
  127. for (let i = 0; i <= index; i++) {
  128. removeClass(
  129. document.querySelector(".hs-select__item" + i),
  130. inRange
  131. );
  132. }
  133. } else {
  134. while (index <= firstIndex) {
  135. removeClass(
  136. document.querySelector(".hs-select__item" + index),
  137. inRange
  138. );
  139. index++;
  140. }
  141. }
  142. }
  143. };
  144. // 鼠标点击
  145. const selectValue = (index, item) => {
  146. if (props.disabled) return;
  147. const len = selectedList.length;
  148. if (len < 2) {
  149. selectedList.push({ item, index });
  150. addClass(document.querySelector("." + voidClass + index), stayClass);
  151. addClass(
  152. document.querySelector(".hs-select__item" + selectedList[0].index),
  153. bothLeftSides
  154. );
  155. if (selectedList[1]) {
  156. if (selectedDirection === "right") {
  157. addClass(
  158. document.querySelector(
  159. ".hs-select__item" + selectedList[1].index
  160. ),
  161. bothRightSides
  162. );
  163. } else {
  164. addClass(
  165. document.querySelector(
  166. ".hs-select__item" + selectedList[1].index
  167. ),
  168. bothLeftSides
  169. );
  170. }
  171. }
  172. if (len === 1) {
  173. // 顺时针排序
  174. if (selectedDirection === "right") {
  175. emit("selectedVal", {
  176. left: selectedList[0].item,
  177. right: selectedList[1].item,
  178. whole: selectedList
  179. });
  180. } else {
  181. emit("selectedVal", {
  182. left: selectedList[1].item,
  183. right: selectedList[0].item,
  184. whole: selectedList
  185. });
  186. }
  187. }
  188. } else {
  189. nextTick(() => {
  190. selectedList.forEach(v => {
  191. removeClass(
  192. document.querySelector("." + voidClass + v.index),
  193. activeClass,
  194. stayClass
  195. );
  196. removeClass(
  197. document.querySelector(".hs-select__item" + v.index),
  198. bothLeftSides,
  199. bothRightSides
  200. );
  201. });
  202. selectedList = [];
  203. overList = [];
  204. for (let i = 0; i <= props.max.length; i++) {
  205. const currentDom = document.querySelector(".hs-select__item" + i);
  206. if (currentDom) {
  207. removeClass(currentDom, inRange);
  208. }
  209. }
  210. selectedList.push({ item, index });
  211. addClass(document.querySelector("." + voidClass + index), stayClass);
  212. addClass(
  213. document.querySelector(".hs-select__item" + selectedList[0].index),
  214. bothLeftSides
  215. );
  216. });
  217. }
  218. };
  219. // 回显数据
  220. const echoView = item => {
  221. if (item.length === 0) return;
  222. if (item.length > 2 || item.length === 1) {
  223. throw "传入的数组长度必须是2";
  224. }
  225. item.sort((a, b) => {
  226. return a - b;
  227. });
  228. addClass(
  229. instance.refs["hsdiv" + props.HsKey + item[0]] as Element,
  230. activeClass,
  231. stayClass
  232. );
  233. addClass(
  234. instance.refs["hstd" + props.HsKey + item[0]] as Element,
  235. bothLeftSides
  236. );
  237. addClass(
  238. instance.refs["hsdiv" + props.HsKey + item[1]] as Element,
  239. activeClass,
  240. stayClass
  241. );
  242. addClass(
  243. instance.refs["hstd" + props.HsKey + item[1]] as Element,
  244. bothRightSides
  245. );
  246. while (item[1] >= item[0]) {
  247. addClass(
  248. instance.refs["hstd" + props.HsKey + item[0]] as Element,
  249. inRange
  250. );
  251. item[0]++;
  252. }
  253. };
  254. onBeforeMount(() => {
  255. nextTick(() => {
  256. echoView(props.echo);
  257. });
  258. });
  259. return () => (
  260. <>
  261. <table cellspacing="0" cellpadding="0">
  262. <tbody>
  263. <tr>
  264. {props.max.map((item, key) => {
  265. return (
  266. <td
  267. data-index={props.HsKey}
  268. ref={`hstd${props.HsKey}${key}`}
  269. class={`hs-select__item${key}`}
  270. onMousemove={() => setCurrentValue(key)}
  271. onMouseleave={() => resetCurrentValue(key)}
  272. onClick={() => selectValue(key, item)}
  273. style={{
  274. cursor: unref(rateDisabled) ? "auto" : "pointer",
  275. textAlign: "center"
  276. }}
  277. key={key}
  278. >
  279. <div
  280. ref={`hsdiv${props.HsKey}${key}`}
  281. class={`hs-item ${[unref(classes)[key] + key]}`}
  282. >
  283. <span>{item}</span>
  284. </div>
  285. </td>
  286. );
  287. })}
  288. </tr>
  289. </tbody>
  290. </table>
  291. </>
  292. );
  293. }
  294. });