PersonList.uvue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <view class="container">
  3. <!-- 列表内容 -->
  4. <!-- #ifdef APP -->
  5. <list-view class="list" :bounces="false" :scroll-y="true" :custom-nested-scroll="true"
  6. @scrolltolower="loadData(null)" associative-container="nested-scroll-view">
  7. <list-item class="list-item" type="10">
  8. <!-- #endif -->
  9. <view class="download-card" v-for="(item, index) in users" :key="index">
  10. <view @click="enterItem(item.id)">
  11. <view class="info-row">
  12. <text class="label">序号:</text>
  13. <text class="value">{{ item.id }}</text>
  14. </view>
  15. <view class="info-row">
  16. <text class="label">用户姓名:</text>
  17. <text class="value">{{ item.name }}</text>
  18. </view>
  19. <view class="info-row">
  20. <text class="label">用户登录账号:</text>
  21. <text class="value">{{ item.username }}</text>
  22. </view>
  23. <view class="info-row">
  24. <text class="label">用户类型:</text>
  25. <text class="value">{{ item.role == 'user' ? '普通用户' : '管理员' }}</text>
  26. </view>
  27. <view class="info-row">
  28. <text class="label">创建时间:</text>
  29. <text
  30. class="value">{{ item.createtime === null ? item.createtime : item.updatetime }}</text>
  31. </view>
  32. </view>
  33. <view class="info-row">
  34. <button class="btn btn-second" type='warn' v-if="item.role == 'user'" @click="del(item.id)">
  35. 删除
  36. </button>
  37. </view>
  38. </view>
  39. <!-- #ifdef APP -->
  40. </list-item type="20">
  41. <list-item class="loading">
  42. <uni-loading :loading="loading" color="#999" :text="loadingText"></uni-loading>
  43. </list-item>
  44. </list-view>
  45. <!-- #endif -->
  46. </view>
  47. </template>
  48. <script setup>
  49. import { ref, reactive } from 'vue'
  50. import { selectPageSql, removeTableData } from '@/api/work';
  51. const backPressOptions = reactive({
  52. from: 'backbutton'
  53. } as OnBackPressOptions)
  54. onBackPress((options : OnBackPressOptions) : boolean | null => {
  55. console.log('onBackPress', options)
  56. // 使用reLaunch代替switchTab,避免多层跳转时的闪回问题
  57. // reLaunch会关闭所有页面并打开到目标页面,适合需要完全重置导航栈的场景
  58. uni.reLaunch({
  59. url: `/pages/mine/index`,
  60. })
  61. // 返回true表示拦截默认返回行为
  62. return true
  63. })
  64. type User = {
  65. id : number,
  66. name : string,
  67. username : string,
  68. role : string,
  69. updatetime : string,
  70. createtime : string
  71. }
  72. var initUser = [] as User[]
  73. var users = ref<User[]>([]);
  74. const loading = ref(false)
  75. const isEnded = ref(false)
  76. const loadingError = ref('')
  77. const currentPage = ref(1)
  78. const loadingText = computed(() : string => {
  79. if (loading.value) {
  80. return "加载中..."
  81. } else if (isEnded.value) {
  82. return "没有更多了"
  83. } else if (loadingError.value.length > 0) {
  84. return loadingError.value
  85. } else {
  86. return ""
  87. }
  88. })
  89. // #ifdef APP-ANDROID
  90. const loadData = (loadComplete : (() => void) | null) {
  91. if (loading.value || isEnded.value) {
  92. return
  93. }
  94. loading.value = true
  95. let offset = currentPage.value === 1 ? 0 : (currentPage.value - 1) * 10
  96. selectPageSql('app_user', 'createtime', offset).then((res : UTSJSONObject) => {
  97. console.log(res)
  98. let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>()
  99. if (dataList != null && dataList.length > 0) {
  100. dataList.forEach(item => {
  101. if (item != null) {
  102. let log = JSON.parse<User>(item.toJSONString());
  103. if (log != null) {
  104. initUser.push(log)
  105. }
  106. }
  107. });
  108. currentPage.value++
  109. } else {
  110. isEnded.value = true
  111. }
  112. users.value = initUser
  113. loading.value = false
  114. if (loadComplete != null) {
  115. loadComplete()
  116. }
  117. })
  118. }
  119. onMounted(() => {
  120. loadData(null)
  121. })
  122. // #endif
  123. const del = (id : number) => {
  124. console.log("删除用户")
  125. console.log(id)
  126. uni.showModal({
  127. title: '系统提示',
  128. content: '确定要删除当前用户?',
  129. cancelText: '取消',
  130. confirmText: '确定',
  131. success: function (res) {
  132. if (res.confirm) {
  133. removeTableData('app_user', 'id', id.toString()).then(res => {
  134. if (res != null) {
  135. let dataList = res?.['data'] as UTSJSONObject[] ?? Array<UTSJSONObject>();
  136. if (dataList != null && dataList.length > 0) {
  137. let data = dataList[0] as boolean ?? false
  138. if (data != null && data == true) {
  139. uni.showToast({
  140. title: "删除成功!",
  141. });
  142. }
  143. }
  144. }
  145. })
  146. console.log(res)
  147. } else {
  148. // 用户取消覆盖
  149. uni.hideLoading();
  150. }
  151. }
  152. });
  153. }
  154. const enterItem = (id : number) => {
  155. uni.navigateTo({
  156. url: `/pages/work/download/DownloadDetail?id=${id}`
  157. });
  158. }
  159. defineExpose({
  160. loadData,
  161. backPressOptions
  162. })
  163. </script>
  164. <style scope>
  165. .container {
  166. padding: 24rpx;
  167. background-color: #f0f4f8;
  168. flex: 1;
  169. display: flex;
  170. flex-direction: column;
  171. font-family: "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif;
  172. /* #ifndef APP-ANDROID */
  173. min-height: 100vh;
  174. /* #endif */
  175. height: 120rpx;
  176. }
  177. .search-bar {
  178. background-color: #ffffff;
  179. border-radius: 10rpx;
  180. box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  181. }
  182. /* 搜索输入框:占满容器剩余空间,放在按钮左侧 */
  183. .search-input {
  184. /* 清除默认输入框样式 */
  185. border: none;
  186. background: transparent;
  187. width: 70%;
  188. margin-left: 10rpx;
  189. }
  190. /* 扫描按钮:放在输入框右侧,距离最右10rpx */
  191. .scan-btn {
  192. justify-content: center;
  193. align-items: center;
  194. /* 新增:按钮内部图标垂直居中 */
  195. /* 关键:右侧10rpx边距,实现"距离最右10rpx" */
  196. margin-left: auto;
  197. /* 自动推到flex容器最右侧 */
  198. margin-right: 10rpx;
  199. /* 与容器右边缘保持10rpx间距 */
  200. }
  201. .download-card {
  202. background: #ffffff;
  203. border-radius: 20rpx;
  204. padding: 24rpx 32rpx;
  205. box-shadow: 0 8rpx 15rpx rgba(0, 43, 92, 0.1);
  206. display: flex;
  207. flex-direction: column;
  208. margin-bottom: 20rpx;
  209. margin-top: 40rpx;
  210. margin-left: 20rpx;
  211. margin-right: 20rpx;
  212. }
  213. .download-card .view {
  214. margin-bottom: 16rpx;
  215. }
  216. /* 信息行 */
  217. .info-row {
  218. display: flex;
  219. flex-direction: row;
  220. /* #ifdef H5 */
  221. font-size: 28rpx;
  222. color: #33475b;
  223. /* #endif */
  224. align-items: center;
  225. }
  226. .info-row>.label {
  227. margin-left: 10rpx;
  228. }
  229. .info-row>.value {
  230. margin-left: 10rpx;
  231. }
  232. .btn-panel {
  233. display: flex;
  234. justify-content: space-between;
  235. align-items: center;
  236. margin-left: 5rpx;
  237. margin-right: 5rpx;
  238. }
  239. .label {
  240. font-weight: bold;
  241. color: #102a43;
  242. min-width: 100rpx;
  243. }
  244. .value {
  245. flex: 1;
  246. white-space: nowrap;
  247. overflow: hidden;
  248. text-overflow: ellipsis;
  249. }
  250. .btn {
  251. align-self: flex-end;
  252. background-color: #00aaff;
  253. color: #fff;
  254. border: none;
  255. border-radius: 32rpx;
  256. padding: 2rpx 30rpx;
  257. font-size: 24rpx;
  258. font-weight: bold;
  259. /* #ifndef APP-ANDROID */
  260. transition: background-color 0.3s ease;
  261. /* #endif */
  262. margin-top: 30rpx;
  263. }
  264. .process-value {
  265. width: 120rpx;
  266. min-width: 100rpx;
  267. text-align: center;
  268. border-radius: 10rpx;
  269. }
  270. .bg-green {
  271. background-color: seagreen;
  272. }
  273. .bg-yellow {
  274. background-color: yellow;
  275. }
  276. .bg-black {
  277. background-color: #102a43;
  278. }
  279. .btn-first {
  280. margin-left: 5rpx;
  281. }
  282. .btn-second {
  283. margin-right: 5rpx;
  284. margin-left: auto;
  285. color: #fff;
  286. background-color: red;
  287. }
  288. .loading {
  289. padding: 30px;
  290. align-items: center;
  291. }
  292. .list {
  293. flex: 1;
  294. background-color: #ffffff;
  295. }
  296. .list-item {
  297. flex-direction: column;
  298. margin-top: 10px;
  299. padding: 10px;
  300. }
  301. </style>