bzkf3 2 gadi atpakaļ
vecāks
revīzija
bde83bdc78

+ 4 - 4
auto-imports.d.ts

@@ -40,9 +40,10 @@ declare global {
   const getCurrentInstance: typeof import('vue')['getCurrentInstance']
   const getCurrentScope: typeof import('vue')['getCurrentScope']
   const h: typeof import('vue')['h']
+  const handleAutoCompleteTask: typeof import('./src/composables/steps')['handleAutoCompleteTask']
+  const handleCompleteTask: typeof import('./src/composables/steps')['handleCompleteTask']
   const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
   const inject: typeof import('vue')['inject']
-  const isDark: typeof import('./src/composables/dark')['isDark']
   const isDefined: typeof import('@vueuse/core')['isDefined']
   const isProxy: typeof import('vue')['isProxy']
   const isReactive: typeof import('vue')['isReactive']
@@ -101,7 +102,6 @@ declare global {
   const toReactive: typeof import('@vueuse/core')['toReactive']
   const toRef: typeof import('vue')['toRef']
   const toRefs: typeof import('vue')['toRefs']
-  const toggleDark: typeof import('./src/composables/dark')['toggleDark']
   const triggerRef: typeof import('vue')['triggerRef']
   const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
   const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
@@ -326,9 +326,10 @@ declare module 'vue' {
     readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
     readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
     readonly h: UnwrapRef<typeof import('vue')['h']>
+    readonly handleAutoCompleteTask: UnwrapRef<typeof import('./src/composables/steps')['handleAutoCompleteTask']>
+    readonly handleCompleteTask: UnwrapRef<typeof import('./src/composables/steps')['handleCompleteTask']>
     readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
     readonly inject: UnwrapRef<typeof import('vue')['inject']>
-    readonly isDark: UnwrapRef<typeof import('./src/composables/dark')['isDark']>
     readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
     readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
     readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
@@ -387,7 +388,6 @@ declare module 'vue' {
     readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
     readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
     readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
-    readonly toggleDark: UnwrapRef<typeof import('./src/composables/dark')['toggleDark']>
     readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
     readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
     readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>

+ 18 - 0
components.d.ts

@@ -10,25 +10,43 @@ export {}
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
+    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDialog: typeof import('element-plus/es')['ElDialog']
+    ElDivider: typeof import('element-plus/es')['ElDivider']
+    ElEmpty: typeof import('element-plus/es')['ElEmpty']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']
+    ElIcon: typeof import('element-plus/es')['ElIcon']
+    ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
+    ElOption: typeof import('element-plus/es')['ElOption']
+    ElPopover: typeof import('element-plus/es')['ElPopover']
     ElRadio: typeof import('element-plus/es')['ElRadio']
     ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
+    ElSelect: typeof import('element-plus/es')['ElSelect']
     ElStep: typeof import('element-plus/es')['ElStep']
     ElSteps: typeof import('element-plus/es')['ElSteps']
+    ElTable: typeof import('element-plus/es')['ElTable']
+    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     'I:healthiconsYes': typeof import('~icons/healthicons/yes')['default']
     'I:mdi:horizontalLine': typeof import('~icons/mdi/horizontal-line')['default']
     'I:mdi:tick': typeof import('~icons/mdi/tick')['default']
+    QuestionDialog: typeof import('./src/components/dtk/question-dialog/index.vue')['default']
     Qxsz: typeof import('./src/components/step/link/qxsz.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
+    SettingDialog: typeof import('./src/components/dtk/setting-dialog/index.vue')['default']
     TheCard: typeof import('./src/components/TheCard.vue')['default']
     TheCounter: typeof import('./src/components/TheCounter.vue')['default']
     TheFooter: typeof import('./src/components/TheFooter.vue')['default']
     TheInput: typeof import('./src/components/TheInput.vue')['default']
   }
+  export interface ComponentCustomProperties {
+    vLoading: typeof import('element-plus/es')['ElLoadingDirective']
+  }
 }

+ 1 - 0
index.html

@@ -6,6 +6,7 @@
   <link rel="icon" href="/favicon.svg" type="image/svg+xml">
   <title>Vitesse Lite</title>
   <meta name="description" content="Opinionated Vite Starter Template">
+  <script src="/config.js"></script>
 </head>
 <body class="font-sans dark:text-white dark:bg-hex-121212">
   <div id="app"></div>

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
   },
   "dependencies": {
     "@vueuse/core": "^9.13.0",
+    "axios": "^1.4.0",
     "element-plus": "^2.3.4",
     "vue": "^3.2.47",
     "vue-router": "^4.1.6"

+ 27 - 6
pnpm-lock.yaml

@@ -4,6 +4,9 @@ dependencies:
   '@vueuse/core':
     specifier: ^9.13.0
     version: 9.13.0(vue@3.2.47)
+  axios:
+    specifier: ^1.4.0
+    version: 1.4.0
   element-plus:
     specifier: ^2.3.4
     version: 2.3.4(vue@3.2.47)
@@ -1894,13 +1897,22 @@ packages:
 
   /asynckit@0.4.0:
     resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
-    dev: true
 
   /available-typed-arrays@1.0.5:
     resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
     engines: {node: '>= 0.4'}
     dev: true
 
+  /axios@1.4.0:
+    resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==}
+    dependencies:
+      follow-redirects: 1.15.2
+      form-data: 4.0.0
+      proxy-from-env: 1.1.0
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
   /balanced-match@1.0.2:
     resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
     dev: true
@@ -2147,7 +2159,6 @@ packages:
     engines: {node: '>= 0.8'}
     dependencies:
       delayed-stream: 1.0.0
-    dev: true
 
   /commander@10.0.0:
     resolution: {integrity: sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==}
@@ -2328,7 +2339,6 @@ packages:
   /delayed-stream@1.0.0:
     resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
     engines: {node: '>=0.4.0'}
-    dev: true
 
   /delegates@1.0.0:
     resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
@@ -3153,6 +3163,16 @@ packages:
     resolution: {integrity: sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==}
     dev: true
 
+  /follow-redirects@1.15.2:
+    resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
+    engines: {node: '>=4.0'}
+    peerDependencies:
+      debug: '*'
+    peerDependenciesMeta:
+      debug:
+        optional: true
+    dev: false
+
   /for-each@0.3.3:
     resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
     dependencies:
@@ -3166,7 +3186,6 @@ packages:
       asynckit: 0.4.0
       combined-stream: 1.0.8
       mime-types: 2.1.35
-    dev: true
 
   /fs-minipass@2.1.0:
     resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
@@ -4161,14 +4180,12 @@ packages:
   /mime-db@1.52.0:
     resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
     engines: {node: '>= 0.6'}
-    dev: true
 
   /mime-types@2.1.35:
     resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
     engines: {node: '>= 0.6'}
     dependencies:
       mime-db: 1.52.0
-    dev: true
 
   /mimic-fn@2.1.0:
     resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
@@ -4895,6 +4912,10 @@ packages:
     resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
     dev: true
 
+  /proxy-from-env@1.1.0:
+    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+    dev: false
+
   /pseudomap@1.0.2:
     resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
     dev: true

+ 42 - 0
public/config.js

@@ -0,0 +1,42 @@
+// 本地开发环境
+const local = {
+  // web_pc: 'https://tyyx.bozedu.top/',
+  // web_mobile: 'https://tyyxm.bozedu.top/',
+  web_pc: 'https://yzy.dev.bozedu.net/',
+  qqyxt: 'https://qqyxt.dev.bozedu.net/',
+  yzy: 'https://yzy.dev.bozedu.net/',
+  api:'https://openapi.dev.bozedu.net/',
+  uc: 'https://uc.dev.bozedu.net/',
+  origin: window.location.origin,
+}
+
+// 测试服环境
+const development = {
+  web_pc: 'https://yzy.dev.bozedu.net/',
+  origin: window.location.origin,
+  qqyxt: 'https://qqyxt.dev.bozedu.net/',
+  yzy: 'https://yzy.dev.bozedu.net/',
+  api:'https://openapi.dev.bozedu.net/',
+  uc: 'https://uc.dev.bozedu.net/',
+}
+
+// // 正式服环境
+const production = {
+  web_pc: 'https://yzy.bozedu.net/',
+  origin: window.location.origin,
+  qqyxt: 'https://qqyxt.bozedu.net/',
+  yzy: 'https://yzy.bozedu.net/',
+  api:'https://openapi.bozedu.net/',
+  uc: 'https://uc.bozedu.net/',
+}
+
+function isWhich() {
+  if (window.location.href.startsWith(development.web_pc)) {
+    return development
+  } else if (window.location.href.startsWith(production.web_pc)) {
+    return production
+  } else {
+    return local
+  }
+}
+window.GLOBAL_CONFIG = isWhich()

+ 5 - 2
shims.d.ts

@@ -18,7 +18,10 @@ declare class LeaderLine {
 }
 
 declare interface Window {
-  handleCompleteTask: (gid: number, pid: number, idy: number) => void
-  handleAutoCompleteTask: () => void
+  GLOBAL_CONFIG: {
+    yzy: string
+  }
+  // handleCompleteTask: (gid: number, pid: number, idy: number) => void
+  // handleAutoCompleteTask: () => void
 }
 

+ 3 - 1
src/App.vue

@@ -1,5 +1,7 @@
 <template>
   <main class="m-auto h-800px w-1200px bg-white">
-    <RouterView />
+    <Suspense>
+      <RouterView />
+    </Suspense>
   </main>
 </template>

+ 0 - 2
src/composables/dark.ts

@@ -1,2 +0,0 @@
-export const isDark = useDark()
-export const toggleDark = useToggle(isDark)

+ 0 - 1
src/composables/index.ts

@@ -1 +0,0 @@
-export * from './dark'

+ 30 - 29
src/composables/steps.ts

@@ -1,38 +1,39 @@
-export const stepsMap = reactive([
-  [
-    [0, 0, 1],
-    [0, 0],
-    [0],
-  ],
-  [
-    [0],
-    [0],
-    [0],
-  ],
-  [
-    [0],
-    [0],
-  ],
-  [
-    [0],
-    [0],
-  ],
-  [
-    [0],
-    [0],
-    [0],
-  ],
-])
+import request from '~/utils/request'
 
 // watch(stepsMap, () => {
 //   sessionStorage.setItem('stepsMap', JSON.stringify(stepsMap))
 // }, { deep: true })
 
-window.handleCompleteTask = function (gid: number, pid: number, cid: number) {
-  stepsMap[gid][pid][cid] = 1
+function handleCompleteTask(gid: number, pid: number, cid: number, val?: unknown) {
+  const _ykl_lc_ = JSON.parse(sessionStorage.getItem('ykl_lc')!)
+  _ykl_lc_.processList[gid][pid][cid] = val || 1
+  request({
+    url: '/yzy/kmksyjlc/save',
+    data: {
+      ykl_id: _ykl_lc_.ykl_id,
+      yk: {
+        ykl_lc: JSON.stringify(_ykl_lc_),
+      },
+    },
+  }).then((res) => {
+    if (res.code === '1') {
+      ElMessage({
+        message: '操作成功',
+        type: 'success',
+        grouping: true,
+      })
+      sessionStorage.setItem('stepsMap', JSON.stringify(_ykl_lc_.processList))
+    }
+  }).catch(() => {
+    ElMessage({
+      message: '操作失败',
+      type: 'error',
+      grouping: true,
+    })
+  })
 }
 
-window.handleAutoCompleteTask = function () {
+export function handleAutoCompleteTask() {
   const { gid, pid, cid } = JSON.parse(sessionStorage.getItem('StepId')!)
-  window.handleCompleteTask(gid, pid, cid)
+  handleCompleteTask(gid, pid, cid)
 }

+ 2 - 2
src/main.ts

@@ -1,5 +1,5 @@
 import { createApp } from 'vue'
-import { createRouter, createWebHistory } from 'vue-router'
+import { createRouter, createWebHashHistory } from 'vue-router'
 import routes from 'virtual:generated-pages'
 import App from './App.vue'
 
@@ -10,7 +10,7 @@ import 'element-plus/es/components/message/style/css'
 
 const app = createApp(App)
 const router = createRouter({
-  history: createWebHistory(import.meta.env.BASE_URL),
+  history: createWebHashHistory(import.meta.env.BASE_URL),
   routes,
 })
 app.use(router)

+ 0 - 20
src/pages/README.md

@@ -1,20 +0,0 @@
-## File-based Routing
-
-Routes will be auto-generated for Vue files in this dir with the same file structure.
-Check out [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) for more details.
-
-### Path Aliasing
-
-`~/` is aliased to `./src/` folder.
-
-For example, instead of having
-
-```ts
-import { isDark } from '../../../../composables'
-```
-
-now, you can use
-
-```ts
-import { isDark } from '~/composables'
-```

+ 4 - 2
src/pages/detail.vue

@@ -1,8 +1,10 @@
 <script setup lang='ts'>
-const { gid, pid, cid } = JSON.parse(sessionStorage.getItem('StepId')!)
+import { handleAutoCompleteTask } from '~/composables/steps'
+
+// const { gid, pid, cid } = JSON.parse(sessionStorage.getItem('StepId')!)
 const router = useRouter()
 function handleCompleteTask() {
-  window.handleCompleteTask((gid), (pid), (cid))
+  handleAutoCompleteTask()
   router.back()
 }
 </script>

+ 161 - 58
src/pages/index.vue

@@ -1,9 +1,61 @@
 <script setup lang="ts" generic="T extends any, O extends any">
-import { stepsMap } from '~/composables/steps'
+import request from '~/utils/request'
+// import { stepsMap } from '~/composables/steps'
+
+const ykl_id = 607
+
+const server = (await request({
+  url: '/yzy/kmksyjlc/detail',
+  data: {
+    ykl_id,
+  },
+})).data.one_info
+
+const ykl_lc = Object.assign(JSON.parse(Object.assign(server.ykl_lc)), { ykl_id })
+sessionStorage.setItem('ykl_lc', JSON.stringify(ykl_lc))
+
+// request({
+//   url: '/yzy/kmksyjlc/save',
+//   data: {
+//     ykl_id,
+//     yk: {
+//       ykl_lc: JSON.stringify({
+//         ...ykl_lc,
+//         processList: [
+//           [
+//             [0, 0, 1],
+//             [0, 0],
+//             [0],
+//           ],
+//           [
+//             [0],
+//             [0],
+//             [0],
+//           ],
+//           [
+//             [0],
+//             [0],
+//           ],
+//           [
+//             [0],
+//             [0],
+//           ],
+//           [
+//             [0],
+//             [0],
+//             [0],
+//           ],
+//         ],
+//       }),
+//     },
+//   },
+// })
+
+const stepsReactiveMap = reactive<unknown[][][]>(ykl_lc.processList)
 
 // 先上传后划块
 const steps = reactive(
-  true
+  ykl_lc.ykj_yjlc === '1'
     ? [
         {
           title: '组卷考试',
@@ -204,13 +256,15 @@ let gid = $ref<number>(0)
 let pids = $ref<number[]>([])
 // const cid = $ref(-1)
 function getGid() {
-  return stepsMap.findLastIndex(item => item.some(subItem => subItem.some(subSubItem => subSubItem)))
+  return stepsReactiveMap.findLastIndex(item => item.some(subItem => subItem.some(subSubItem => judgeStepCompleted(subSubItem))))
 }
 
 function getPids() {
-  return stepsMap.map((item, idx) => (idx < gid ? 1 : 0) + item.findLastIndex(subItem => subItem.some(subSubItem => subSubItem)))
+  return stepsReactiveMap.map((item, idx) => (idx < gid ? 1 : 0) + item.findLastIndex(subItem => subItem.some(subSubItem => judgeStepCompleted(subSubItem))))
 }
-watch(() => stepsMap, (val) => {
+watch(() => stepsReactiveMap, (val) => {
+  sessionStorage.setItem('stepsMap', JSON.stringify(val))
+
   gid = getGid()
   pids = getPids()
 }, {
@@ -237,7 +291,7 @@ const lineList: any[][][] = []
 //           size: 6,
 //           startSocket: 'right',
 //           endSocket: 'left',
-//           color: stepsMap[currentStep][idx][idy] ? '#003eee' : '#a3a3a3',
+//           color: stepsReactiveMap[currentStep][idx][idy] ? '#003eee' : '#a3a3a3',
 //         },
 //       )
 //       lineList.push(line)
@@ -249,60 +303,71 @@ function handleSwitchGid(id: number) {
   currentStep = id
 }
 
-watch(() => currentStep, (val, old) => {
-  if (old !== undefined)
-    lineList[old].forEach(lines => lines.forEach(line => line?.hide('none')))
-  if (lineList[val]?.length) {
-    lineList[val].forEach(lines => lines.forEach(line => line?.show('none')))
-  }
-  else {
-    nextTick(() => {
-      CardsRef.forEach((cards, idx) => {
-        if (idx === CardsRef.length - 1)
-          return
-        cards.forEach((card, idy) => {
-          if (card === null || CardsRef[idx + 1][0] === null)
+onMounted(() => {
+  watch(() => currentStep, (val, old) => {
+    if (old !== undefined)
+      lineList[old].forEach(lines => lines.forEach(line => line?.hide('none')))
+    if (lineList[val]?.length) {
+      lineList[val].forEach(lines => lines.forEach(line => line?.show('none')))
+    }
+    else {
+      nextTick(() => {
+        CardsRef.forEach((cards, idx) => {
+          if (idx === CardsRef.length - 1)
             return
-          const line = new LeaderLine(
-            card.getDom(),
-            CardsRef[idx + 1][0].getDom(),
-            {
-              path: 'grid',
-              endPlug: 'behind',
-              size: 6,
-              startSocket: 'right',
-              endSocket: 'left',
-              color: stepsMap[currentStep][idx][idy] ? '#003eee' : '#a3a3a3',
-            },
-          )
-          line?.position()
-          if (stepsMap[currentStep][idx][idy])
-            document.querySelectorAll('.leader-line')[line._id as number - 1]?.classList.add('z10')
+          cards.forEach((card, idy) => {
+            if (card === null || CardsRef[idx + 1][0] === null)
+              return
+            const line = new LeaderLine(
+              card.getDom(),
+              CardsRef[idx + 1][0].getDom(),
+              {
+                path: 'grid',
+                endPlug: 'behind',
+                size: 6,
+                startSocket: 'right',
+                endSocket: 'left',
+                color: stepsReactiveMap[currentStep][idx][idy] ? '#003eee' : '#a3a3a3',
+              },
+            )
+            line?.position()
+            if (stepsReactiveMap[currentStep][idx][idy])
+              document.querySelectorAll('.leader-line')[line._id as number - 1]?.classList.add('z10')
 
-          lineList[val] = lineList[val] || []
-          lineList[val][idx] = lineList[val][idx] || []
-          lineList[val][idx][idy] = line
+            lineList[val] = lineList[val] || []
+            lineList[val][idx] = lineList[val][idx] || []
+            lineList[val][idx][idy] = line
+          })
         })
       })
-    })
-  }
-}, {
-  immediate: true,
+    }
+  }, {
+    immediate: true,
+  })
 })
+
 const router = useRouter()
-function handleClickTask(currentStep: number, idx: number, idy: number) {
+
+function routerPush(path: string) {
+  router.push(path)
+}
+function windowPushState(path: string) {
+  window.open(`${location.origin}/${path}`, '_self')
+}
+
+function handleValidTask(currentStep: number, idx: number, idy: number) {
   let lastIdx = idx
   let lastStep = currentStep
-  const lastTasks = idx > 0 ? stepsMap[currentStep][lastIdx = idx - 1] : currentStep > 0 ? stepsMap[lastStep = currentStep - 1][lastIdx = stepsMap[currentStep - 1].length - 1] : []
+  const lastTasks = idx > 0 ? stepsReactiveMap[currentStep][lastIdx = idx - 1] : currentStep > 0 ? stepsReactiveMap[lastStep = currentStep - 1][lastIdx = stepsReactiveMap[currentStep - 1].length - 1] : []
 
   if (lastTasks.every((item, idz) => {
     if (steps[lastStep].children[lastIdx].children[idz].optional)
       return true
     else
-      return item
+      return !!item
   })) {
     sessionStorage.setItem('StepId', JSON.stringify({ gid: currentStep, pid: idx, cid: idy }))
-    router.push('/detail')
+    return true
   }
   else {
     ElMessage({
@@ -310,11 +375,12 @@ function handleClickTask(currentStep: number, idx: number, idy: number) {
       type: 'warning',
       grouping: true,
     })
+    return false
   }
 }
 
-function beforeClickTask() {
-  const continueDoTask = Math.random() > 0.8// false
+function beforeClickTask(gid: number, pid: number, idy: number) {
+  const continueDoTask = true
   if (!continueDoTask) {
     ElMessage({
       message: '无权操作',
@@ -322,19 +388,56 @@ function beforeClickTask() {
       grouping: true,
     })
   }
+  else {
+    return handleValidTask(gid, pid, idy)
+  }
   return continueDoTask
 }
 
-function handleCompleteTask(gid: number, pid: number, idy: number) {
-  if (stepsMap[gid][pid][idy] === 1) {
+function judgeStepCompleted(val: unknown) {
+  return (!!val) || (typeof val === 'object' && !!(val?.value))
+}
+
+function handleCompleteTask(gid: number, pid: number, cid: number, val?: unknown) {
+  const _ykl_lc_ = JSON.parse(sessionStorage.getItem('ykl_lc')!)
+  _ykl_lc_.processList[gid][pid][cid] = val || 1
+  request({
+    url: '/yzy/kmksyjlc/save',
+    data: {
+      ykl_id,
+      yk: {
+        ykl_lc: JSON.stringify(_ykl_lc_),
+      },
+    },
+  }).then((res) => {
+    if (res.code === '1') {
+      ElMessage({
+        message: '操作成功',
+        type: 'success',
+        grouping: true,
+      })
+      stepsReactiveMap[gid][pid][cid] = val || 1
+    }
+  }).catch(() => {
+    ElMessage({
+      message: '操作失败',
+      type: 'error',
+      grouping: true,
+    })
+  })
+}
+
+function handleJumpTask(gid: number, pid: number, idy: number) {
+  if (judgeStepCompleted(stepsReactiveMap[gid][pid][idy])) {
     return ElMessage({
       message: '该任务已完成',
       type: 'warning',
       grouping: true,
     })
   }
-  window.handleCompleteTask(gid, pid, idy)
-  if (pid === stepsMap[gid].length - 1)
+  // stepsReactiveMap[gid][pid][idy] = 1
+  handleCompleteTask(gid, pid, idy)
+  if (pid === stepsReactiveMap[gid].length - 1)
     return
   const line = lineList[gid][pid][idy]
   line.setOptions({ color: '#003eee' })
@@ -381,19 +484,19 @@ onBeforeRouteLeave(() => {
           <the-card
             v-for="(task, idy) in step.children " :key="idy"
             :ref="el => { CardsRef[idx] = CardsRef[idx] || []; CardsRef[idx][idy] = el as any }" :title="task.title"
-            :description="task.description" :completed="!!stepsMap[currentStep][idx][idy]"
+            :description="task.description" :completed="judgeStepCompleted(stepsReactiveMap[currentStep][idx][idy])"
           >
             <template #operate>
               <template v-if="task.title === '预划考号区域'">
                 <div
                   class="min-w-60px cursor-pointer rounded bg-light-50 py-3px text-center text-xs"
-                  @click="beforeClickTask() && handleClickTask(currentStep, idx, idy)"
+                  @click="beforeClickTask(currentStep, idx, idy) && windowPushState('/dist/index.html')"
                 >
-                  {{ !!stepsMap[currentStep][idx][idy] ? '已经完成' : '立即开始' }}
+                  {{ judgeStepCompleted(stepsReactiveMap[currentStep][idx][idy]) ? '已经完成' : '立即开始' }}
                 </div>
                 <div
                   class="min-w-60px cursor-pointer rounded bg-light-50 py-3px text-center text-xs"
-                  @click="beforeClickTask() && handleCompleteTask(currentStep, idx, idy)"
+                  @click="beforeClickTask(currentStep, idx, idy) && handleJumpTask(currentStep, idx, idy)"
                 >
                   {{ '跳过' }}
                 </div>
@@ -401,9 +504,9 @@ onBeforeRouteLeave(() => {
               <template v-else>
                 <div
                   class="min-w-60px cursor-pointer rounded bg-light-50 py-3px text-center text-xs"
-                  @click="beforeClickTask() && handleClickTask(currentStep, idx, idy)"
+                  @click="beforeClickTask(currentStep, idx, idy) && routerPush('detail')"
                 >
-                  {{ !!stepsMap[currentStep][idx][idy] ? '已经完成' : '立即开始' }}
+                  {{ judgeStepCompleted(stepsReactiveMap[currentStep][idx][idy]) ? '已经完成' : '立即开始' }}
                 </div>
               </template>
             </template>
@@ -414,7 +517,7 @@ onBeforeRouteLeave(() => {
                   <el-link type="primary">
                     修改试题答案
                   </el-link>
-                  <qxsz :disabled="!!stepsMap[currentStep][idx][idy]" />
+                  <qxsz :disabled="judgeStepCompleted(stepsReactiveMap[currentStep][idx][idy])" />
                   <el-link type="primary">
                     标记缺考
                   </el-link>

+ 87 - 0
src/store/index.ts

@@ -0,0 +1,87 @@
+import type { IUser } from './user'
+
+// 以下代码在build时自动移除,无需手动注释
+// #ifdef DEV
+sessionStorage.setItem('userInfo', JSON.stringify({
+  user_id: '244521',
+  user_name: 'lwadmin',
+  email: 'lwadmin@bozedu.net',
+  lastlogintime: '2023-04-13 16:27:42',
+  regdate: '2021-08-18 17:08:49',
+  status: '0',
+  user_role_id: '72',
+  user_role_name: '学校管理员',
+  user_avatar: {
+    big: 'https://openapi.dev.bozedu.net/template/default/static/img/avatar_teacher_big.png',
+    middle: 'https://openapi.dev.bozedu.net/template/default/static/img/avatar_teacher_middle.png',
+    small: 'https://openapi.dev.bozedu.net/template/default/static/img/avatar_teacher_small.png',
+  },
+  user_no: { no_title: '学号', no: '' },
+  token: '0036PlXjuFCm7ynYhfQD4PTygChdt85Cy85yHL1QzTyNEP1McOL9j1fhEhr4ZxcXfREXvnqSqRx7mqFt5bedpJ_a7DoM',
+  user_realname: '李文校管dev',
+  user_phone: '',
+  idcard: '',
+  gender: '0',
+  gender_char: '保密',
+  qq: '',
+  nationality: '',
+  intro: '',
+  address: '',
+  education: '',
+  area_info: {
+    area_id1: '10',
+    area_id2: '166',
+    area_id3: '2074',
+    area_id4: '14296',
+    area_id1_char: '江苏省',
+    area_id2_char: '苏州市',
+    area_id3_char: '相城区',
+    area_id4_char: '元和街道',
+    area_code1: '320000000000',
+    area_code2: '320500000000',
+    area_code3: '320507000000',
+    area_code4: '',
+    area_code_dist: '320507000000',
+  },
+  sm_info: {
+    sm_id: '267',
+    adminid: '155033',
+    sm_name: '博智测试学校',
+    is_org: '0',
+    up_org: '381',
+    area_id1: '10',
+    area_id2: '166',
+    area_id3: '2074',
+    area_id4: '14296',
+    major_mode: '1',
+    powers: { vip_shiti: '0', vip_sucai: '1', vip_aicheck: '1' },
+  },
+  cm_info: [],
+  first_cm_id: '',
+  first_cm_name: '',
+  renke_grade: [],
+  renke_subject: {},
+  related_desc: '暂无任课',
+  bind3rd: { wechat: '0' },
+  my_org: [],
+  org_info: {
+    org: null,
+    org_id: null,
+    telephone: '',
+    telephone_short: '',
+    is_org: '1',
+    up_org: null,
+    up_org_name: null,
+    up_org_info: { sm_id: '', sm_name: '' },
+  },
+}))
+// #endif
+
+export const user = ref<IUser>(JSON.parse(sessionStorage.getItem('userInfo') ?? '{}'))
+
+watch(
+  () => user.value,
+  (val) => {
+    sessionStorage.setItem('userInfo', JSON.stringify(val))
+  },
+)

+ 171 - 0
src/store/user.d.ts

@@ -0,0 +1,171 @@
+export interface User_avatar {
+	big: string;
+	middle: string;
+	small: string;
+}
+
+export interface User_no {
+	no_title: string;
+	no: string;
+}
+
+export interface Area_info {
+	area_id1: string;
+	area_id2: string;
+	area_id3: string;
+	area_id4: string;
+	area_id1_char: string;
+	area_id2_char: string;
+	area_id3_char: string;
+	area_id4_char: string;
+	area_code1: string;
+	area_code2: string;
+	area_code3: string;
+	area_code4: string;
+	area_code_dist: string;
+}
+
+export interface Power {
+	vip_shiti: string;
+	vip_sucai: string;
+	vip_aicheck: string;
+}
+
+export interface Sm_info {
+	sm_id: string;
+	adminid: string;
+	sm_name: string;
+	is_org: string;
+	up_org: string;
+	area_id1: string;
+	area_id2: string;
+	area_id3: string;
+	area_id4: string;
+	major_mode: string;
+	powers: Power;
+}
+
+export interface Bind3rd {
+	wechat: string;
+}
+
+export interface Up_org_info {
+	sm_id: string;
+	sm_name: string;
+}
+
+export interface Org_info {
+	org: string;
+	telephone: string;
+	telephone_short: string;
+	is_org: string;
+	up_org: string;
+	up_org_info: Up_org_info;
+}
+
+export interface Pan {
+	unit: string;
+	size: string;
+	used: string;
+	desc: string;
+}
+
+export interface Base_url {
+	aboutus: string;
+	file: string;
+	vpn: string;
+	uc: string;
+	yzy: string;
+	kzkt: string;
+	openapi: string;
+	site_zhkt_api: string;
+	yxxt: string;
+}
+
+export interface Kzkt {
+	code: string;
+	name: string;
+	icon: string;
+	cate: string;
+	type: string;
+	url: string;
+}
+
+export interface Yzy {
+	code: string;
+	name: string;
+	icon: string;
+	cate: string;
+	type: string;
+	url: string;
+}
+
+export interface Zhkt {
+	code: string;
+	name: string;
+	icon: string;
+	cate: string;
+	type: string;
+	url: string;
+}
+
+export interface Role_system {
+	kzkt: Kzkt;
+	yzy: Yzy;
+	zhkt: Zhkt;
+}
+
+export interface App_url {
+	a119: string;
+	a120: string;
+	a121: string;
+	a122: string;
+	a123: string;
+	a124: string;
+	a125: string;
+	a126: string;
+	a127: string;
+	a128: string;
+	a129: string;
+	a130: string;
+	a131: string;
+	a132: string;
+}
+
+export interface IUser {
+	user_id: string;
+	user_name: string;
+	email: string;
+	lastlogintime: string;
+	user_role_id: string;
+	user_role_name: string;
+	user_avatar: User_avatar;
+	user_no: User_no;
+	token: string;
+	user_realname: string;
+	user_phone: string;
+	idcard: string;
+	gender: string;
+	gender_char: string;
+	qq: string;
+	nationality: string;
+	address: string;
+	education: string;
+	area_info: Area_info;
+	sm_info: Sm_info;
+	cm_info: any[];
+	first_cm_id: string;
+	first_cm_name: string;
+	related_desc: string;
+	bind3rd: Bind3rd;
+	org_info: Org_info;
+	pan: Pan;
+	safe_tips: string[];
+	update_center: string;
+	base_url: Base_url;
+	role_system: Role_system;
+	user_score: string;
+	product: string[];
+	app_url: App_url;
+	cpm_access_level: string;
+}

+ 96 - 0
src/utils/request.ts

@@ -0,0 +1,96 @@
+import axios from 'axios'
+import type { AxiosRequestConfig } from 'axios'
+import { user } from '~/store/index'
+
+const token = user.value?.token
+export interface Response {
+  code: string
+  data: any
+  msg: string
+}
+
+const instance = axios.create({
+  baseURL: window.GLOBAL_CONFIG.yzy,
+  timeout: 180 * 1000,
+  headers: {
+    'Content-Type': 'application/x-www-form-urlencoded',
+  },
+  method: 'post',
+})
+
+instance.interceptors.request.use(
+  async (config) => {
+    if (config.method?.toLocaleLowerCase() === 'get') {
+      config.params = Object.assign({ token }, config.params)
+    }
+    else {
+      config.data = Object.assign(
+        {
+          token,
+          client: 'web',
+          api: 'json',
+          issubmit: (config.url?.endsWith('add') || config.url?.endsWith('edit')) ? '1' : undefined,
+        },
+        config.data)
+    }
+    return config
+  },
+  (error) => {
+    console.error('request error: ', error)
+    return Promise.reject(error)
+  },
+)
+
+// response interceptor
+instance.interceptors.response.use(
+  (response) => {
+    response.data.code = response.data?.code?.toString()
+    response.data.msg = response.data.msg.replaceAll(/<.*?>/g, ' ')
+    const { code, msg } = response.data
+    if (code !== '1')
+      ElMessage.error(msg)
+
+    return response.data
+  },
+  (error) => {
+    console.error(`response error: ${error}`)
+    return Promise.reject(error)
+  },
+)
+
+export default (config: AxiosRequestConfig): Promise<Response> => instance.request(config)
+
+function obj2form(data: { [key: string]: any }) {
+  const formData = new FormData()
+  Object.keys(data).forEach(key => formData.append(key, data[key]))
+  return formData
+}
+
+export const REQUEST = {
+  empty: axios,
+  default: instance,
+  import: (c: Partial<AxiosRequestConfig>) => instance({
+    timeout: 10 * 60 * 1000,
+    transformRequest: [obj2form],
+    ...c,
+  }),
+  upload: (c: Partial<AxiosRequestConfig>) => instance({
+    timeout: 3 * 60 * 1000,
+    transformRequest: [obj2form],
+    ...c,
+  }),
+  download: (c: Partial<AxiosRequestConfig>) => instance({
+    timeout: 1 * 60 * 1000,
+    method: 'get',
+    params: { token, limit: 10000, page: 1, api: 'xls', ...c },
+  }),
+}
+
+export function download(url: string, data?: object | null) {
+  const params = Object.assign({ token, limit: 10000, page: 1, api: 'xls' }, data)
+  const paramsStr = Object.entries(params).map(([k, v]) => `${k}=${v}`).join('&')
+  const el = document.createElement('a')
+  const href = `${window.GLOBAL_CONFIG.api}${url}?${paramsStr}`
+  el.setAttribute('href', href)
+  el.click()
+}