uat_us
parent
cc16889f44
commit
3e3e54ed8f
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compact": false,
|
||||
"presets": ["env", "stage-0"],
|
||||
"plugins": ["transform-runtime"]
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
|
@ -0,0 +1,10 @@
|
|||
VUE_FILE_PATH = 'https://zyypacs-code.oss-cn-shanghai.aliyuncs.com'
|
||||
|
||||
|
||||
OSS_REGION = 'oss-cn-shanghai'
|
||||
|
||||
OSS_BUCKET = 'zyypacs-code'
|
||||
|
||||
OSS_ACCESS_KEY_ID = 'mpXG7Nu6zTpsDrI1'
|
||||
|
||||
OSS_ACCESS_KEY_SECRET = 'yNINcEb099SkNfF6vYKaoP8TZNI3xZ'
|
|
@ -0,0 +1,48 @@
|
|||
ENV = 'development'
|
||||
NODE_ENV = 'development'
|
||||
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
VUE_APP_IS_TEST = false
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = 'http://123.56.94.154:7000'
|
||||
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = false
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = false
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = true
|
||||
|
||||
# 密码校验规则
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = false
|
||||
|
||||
|
||||
# dicom文件地址
|
||||
VUE_APP_DICOM_PATH = 'https://zyypacs.oss-cn-shanghai.aliyuncs.com'
|
||||
|
||||
VUE_APP_DICOM_USA_PATH = 'https://zyypacs-usa.oss-us-west-1.aliyuncs.com'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs'
|
||||
|
||||
VUE_APP_OSS_PATH = '/dev/dist'
|
|
@ -0,0 +1,41 @@
|
|||
# just a flag
|
||||
ENV = 'prod'
|
||||
NODE_ENV = 'prod'
|
||||
#process.env.NODE_ENV
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = true
|
||||
|
||||
# dicom文件地址
|
||||
# VUE_APP_DICOM_PATH = 'http://101.132.193.237:7080'
|
||||
VUE_APP_DICOM_PATH = 'https://zyypacs-prod.oss-cn-shanghai.aliyuncs.com'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs-prod'
|
||||
|
||||
|
||||
VUE_APP_OSS_PATH = '/prod/dist'
|
|
@ -0,0 +1,46 @@
|
|||
# just a flag
|
||||
ENV = 'production'
|
||||
NODE_ENV = 'production'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
VUE_APP_IS_TEST = true
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = false
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = false
|
||||
|
||||
|
||||
|
||||
# dicom文件地址
|
||||
VUE_APP_DICOM_PATH = 'https://zyypacs.oss-cn-shanghai.aliyuncs.com'
|
||||
#VUE_APP_DICOM_PATH = 'http://123.56.94.154:7000'
|
||||
#VUE_APP_DICOM_PATH = 'https://zyypacs-mdc.oss-cn-shanghai.aliyuncs.com'
|
||||
|
||||
VUE_APP_DICOM_USA_PATH = 'https://zyypacs-usa.oss-us-west-1.aliyuncs.com'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs'
|
||||
|
||||
VUE_APP_OSS_PATH = '/test/dist'
|
|
@ -0,0 +1,34 @@
|
|||
# just a flag
|
||||
ENV = 'prop'
|
||||
NODE_ENV = 'prop'
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = true
|
||||
|
||||
# dicom文件地址
|
||||
VUE_APP_DICOM_PATH = 'http://123.56.94.154:7020'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs'
|
|
@ -0,0 +1,41 @@
|
|||
# just a flag
|
||||
ENV = 'production'
|
||||
NODE_ENV = 'production'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = true
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = true
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = true
|
||||
|
||||
# dicom文件地址
|
||||
VUE_APP_DICOM_PATH = 'https://zyypacs-uat.oss-cn-shanghai.aliyuncs.com'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-cn-shanghai'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs-uat'
|
||||
|
||||
VUE_APP_OSS_PATH = '/uat/dist'
|
|
@ -0,0 +1,40 @@
|
|||
# just a flag
|
||||
ENV = 'production'
|
||||
NODE_ENV = 'production'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = false
|
||||
|
||||
# 是否开启长时间无操作锁定弹框 true:是 false:否
|
||||
VUE_APP_LOCK_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOCK_FOR_TIME = 900
|
||||
|
||||
# 是否开启长时间无操作登出 true:是 false:否
|
||||
VUE_APP_LOGOUT_FOR_PERMISSION = false
|
||||
|
||||
# 无操作锁定弹框判断时间 单位:秒
|
||||
VUE_APP_LOGOUT_FOR_TIME = 1800
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_PERMISSION = false
|
||||
|
||||
# 是否开启密码正则验证 true:是 false:否
|
||||
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
|
||||
|
||||
# 是否开启文档签署验证 true:是 false:否
|
||||
VUE_APP_WORD_FOR_PERMISSION = true
|
||||
|
||||
# dicom文件地址
|
||||
VUE_APP_DICOM_PATH = 'https://zyypacs-usa.oss-us-west-1.aliyuncs.com'
|
||||
|
||||
VUE_APP_DICOM_USA_PATH = 'https://zyypacs-usa.oss-us-west-1.aliyuncs.com'
|
||||
|
||||
VUE_APP_OSS_CONFIG_REGION = 'oss-us-west-1'
|
||||
|
||||
VUE_APP_OSS_CONFIG_BUCKET = 'zyypacs-usa'
|
||||
|
||||
VUE_APP_OSS_PATH = '/usa/dist'
|
|
@ -0,0 +1,42 @@
|
|||
build/*.js
|
||||
src/assets
|
||||
src/utils/*
|
||||
public
|
||||
dist
|
||||
|
||||
src/*
|
||||
src/views/dictionary/checkConfig/*
|
||||
src/views/trials/trials-panel/trial-summary/*
|
||||
src/main.js
|
||||
src/views/trials/trials-panel/reading/reading-tracking/*
|
||||
src/views/trials/trials-panel/reading/pm-medical-feedback/*
|
||||
src/views/trials/trials-panel/reading/consistency-analysis/*
|
||||
src/views/trials/trials-panel/reading/referee-allocation/*
|
||||
src/views/trials/trials-list/components/TrialForm
|
||||
src/views/trials/trials-panel/reading/read-task-allocation/*
|
||||
src/views/blindResumeInfo/*
|
||||
src/views/trials/trials-panel/visit/crc-upload/*
|
||||
src/views/trials/trials-panel/reading/dicoms/customize/*
|
||||
src/views/trials/trials-panel/subject/brain-metastasis/*
|
||||
src/views/trials/trials-panel/setting/reading-unit/components/*
|
||||
src/cornerstonejs/*
|
||||
src/components/clinicalDataQuestions/*
|
||||
src/views/dictionary/template/*
|
||||
src/views/trials/trials-panel/reading/reading-tracking/components/*
|
||||
src/views/trials/trials-panel/trial-summary/audit-record/*
|
||||
src/views/dictionary/template/components/*
|
||||
src/views/trials/trials-panel/reading/task-allocation/*
|
||||
src/views/trials/trials-panel/clinical-data/*
|
||||
src/views/trials/trials-panel/visit/qc-check/components/clinicalData/*
|
||||
src/views/trials/trials-panel/subject/reading-period/*
|
||||
src/views/dictionary/template/email/*
|
||||
src/views/trials/trials-panel/enrolled-reviewers/stats/components/AddWorkload.vue
|
||||
src/views/trials/trials-workbench/components/clinicalDataPM.vue
|
||||
src/views/trials/trials-workbench/*
|
||||
src/components/*
|
||||
src/views/resumeInfo/*
|
||||
src/layout/*
|
||||
src/views/trials/trials-panel/setting/*
|
||||
src/views/reviewers/*
|
||||
src/api/reviewers
|
||||
src/views/trials/trials-panel/setting/trial-config/*
|
|
@ -0,0 +1,278 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
sourceType: 'module'
|
||||
},
|
||||
globals: {
|
||||
"zzSessionStorage": true
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
extends: ["plugin:vue/recommended"],
|
||||
|
||||
// add your custom rules here
|
||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
||||
rules: {
|
||||
"vue/max-attributes-per-line": [
|
||||
2,
|
||||
{
|
||||
singleline: 10,
|
||||
multiline: {
|
||||
max: 1,
|
||||
allowFirstLine: false
|
||||
}
|
||||
}
|
||||
],
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
"vue/multiline-html-element-content-newline": "off",
|
||||
"vue/name-property-casing": ["error", "PascalCase"],
|
||||
"vue/no-v-html": "off",
|
||||
"accessor-pairs": 2,
|
||||
"arrow-spacing": [
|
||||
2,
|
||||
{
|
||||
before: true,
|
||||
after: true
|
||||
}
|
||||
],
|
||||
"block-spacing": [2, "always"],
|
||||
"brace-style": [
|
||||
2,
|
||||
"1tbs",
|
||||
{
|
||||
allowSingleLine: true
|
||||
}
|
||||
],
|
||||
camelcase: [
|
||||
0,
|
||||
{
|
||||
properties: "always"
|
||||
}
|
||||
],
|
||||
"comma-dangle": [2, "never"],
|
||||
"comma-spacing": [
|
||||
2,
|
||||
{
|
||||
before: false,
|
||||
after: true
|
||||
}
|
||||
],
|
||||
"comma-style": [2, "last"],
|
||||
"constructor-super": 2,
|
||||
curly: [2, "multi-line"],
|
||||
"dot-location": [2, "property"],
|
||||
"eol-last": 2,
|
||||
eqeqeq: ["error", "always", { null: "ignore" }],
|
||||
"generator-star-spacing": [
|
||||
2,
|
||||
{
|
||||
before: true,
|
||||
after: true
|
||||
}
|
||||
],
|
||||
"handle-callback-err": [2, "^(err|error)$"],
|
||||
indent: [
|
||||
2,
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1
|
||||
}
|
||||
],
|
||||
"jsx-quotes": [2, "prefer-single"],
|
||||
"key-spacing": [
|
||||
2,
|
||||
{
|
||||
beforeColon: false,
|
||||
afterColon: true
|
||||
}
|
||||
],
|
||||
"keyword-spacing": [
|
||||
2,
|
||||
{
|
||||
before: true,
|
||||
after: true
|
||||
}
|
||||
],
|
||||
"new-cap": [
|
||||
2,
|
||||
{
|
||||
newIsCap: true,
|
||||
capIsNew: false
|
||||
}
|
||||
],
|
||||
"new-parens": 2,
|
||||
"no-array-constructor": 2,
|
||||
"no-caller": 2,
|
||||
"no-console": "off",
|
||||
"no-class-assign": 2,
|
||||
"no-cond-assign": 2,
|
||||
"no-const-assign": 2,
|
||||
"no-control-regex": 0,
|
||||
"no-delete-var": 2,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-class-members": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty-pattern": 2,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": [2, "functions"],
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inner-declarations": [2, "functions"],
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": [
|
||||
2,
|
||||
{
|
||||
allowLoop: false,
|
||||
allowSwitch: false
|
||||
}
|
||||
],
|
||||
"no-lone-blocks": 2,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [
|
||||
2,
|
||||
{
|
||||
max: 1
|
||||
}
|
||||
],
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-in-lhs": 2,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-symbol": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-path-concat": 2,
|
||||
"no-proto": 2,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-return-assign": [2, "except-parens"],
|
||||
"no-self-assign": 2,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unmodified-loop-condition": 2,
|
||||
"no-unneeded-ternary": [
|
||||
2,
|
||||
{
|
||||
defaultAssignment: false
|
||||
}
|
||||
],
|
||||
"no-unreachable": 2,
|
||||
"no-unsafe-finally": 2,
|
||||
"no-unused-vars": [
|
||||
2,
|
||||
{
|
||||
vars: "all",
|
||||
args: "none"
|
||||
}
|
||||
],
|
||||
"no-useless-call": 2,
|
||||
"no-useless-computed-key": 2,
|
||||
"no-useless-constructor": 2,
|
||||
"no-useless-escape": 0,
|
||||
"no-whitespace-before-property": 2,
|
||||
"no-with": 2,
|
||||
"one-var": [
|
||||
2,
|
||||
{
|
||||
initialized: "never"
|
||||
}
|
||||
],
|
||||
"operator-linebreak": [
|
||||
2,
|
||||
"after",
|
||||
{
|
||||
overrides: {
|
||||
"?": "before",
|
||||
":": "before"
|
||||
}
|
||||
}
|
||||
],
|
||||
"padded-blocks": [2, "never"],
|
||||
quotes: [
|
||||
2,
|
||||
"single",
|
||||
{
|
||||
avoidEscape: true,
|
||||
allowTemplateLiterals: true
|
||||
}
|
||||
],
|
||||
semi: [2, "never"],
|
||||
"semi-spacing": [
|
||||
2,
|
||||
{
|
||||
before: false,
|
||||
after: true
|
||||
}
|
||||
],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-unary-ops": [
|
||||
2,
|
||||
{
|
||||
words: true,
|
||||
nonwords: false
|
||||
}
|
||||
],
|
||||
"spaced-comment": [
|
||||
2,
|
||||
"always",
|
||||
{
|
||||
markers: [
|
||||
"global",
|
||||
"globals",
|
||||
"eslint",
|
||||
"eslint-disable",
|
||||
"*package",
|
||||
"!",
|
||||
","
|
||||
]
|
||||
}
|
||||
],
|
||||
"template-curly-spacing": [2, "never"],
|
||||
"use-isnan": 2,
|
||||
"valid-typeof": 2,
|
||||
"wrap-iife": [2, "any"],
|
||||
"yield-star-spacing": [2, "both"],
|
||||
yoda: [2, "never"],
|
||||
"prefer-const": 2,
|
||||
//"no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
|
||||
"object-curly-spacing": [
|
||||
2,
|
||||
"always",
|
||||
{
|
||||
objectsInObjects: false
|
||||
}
|
||||
],
|
||||
"array-bracket-spacing": [2, "never"]
|
||||
}
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
tests/**/coverage/
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
|
@ -0,0 +1 @@
|
|||
12
|
|
@ -0,0 +1 @@
|
|||
12
|
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"name": "IRCIS",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve --open",
|
||||
"build": "vue-cli-service build",
|
||||
"build:prod": "vue-cli-service build --mode prod",
|
||||
"build:uat": "vue-cli-service build --mode uat",
|
||||
"build:usa": "vue-cli-service build --mode usa",
|
||||
"pre": "vue-cli-service build --mode pre",
|
||||
"i18n": "npm run i18n:zh && npm run i18n:en",
|
||||
"i18n:zh": "node i18nGenerate.js lang=zh keyCol=5 valCol=6",
|
||||
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ffmpeg/core": "^0.10.0",
|
||||
"@ffmpeg/ffmpeg": "^0.10.1",
|
||||
"@microsoft/signalr": "^6.0.8",
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"ali-oss": "^6.17.1",
|
||||
"axios": "0.18.1",
|
||||
"copy-webpack-plugin": "^4.5.2",
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "^6.0.8",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.7",
|
||||
"echarts": "^4.8.0",
|
||||
"element-ui": "^2.15.8",
|
||||
"exceljs": "^4.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"hammerjs": "^2.0.8",
|
||||
"js-md5": "^0.7.3",
|
||||
"jszip": "^3.7.1",
|
||||
"moment": "^2.27.0",
|
||||
"normalize.css": "7.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "2.4.0",
|
||||
"pdfobject": "^2.2.8",
|
||||
"popper.js": "^1.16.1",
|
||||
"screenfull": "^4.2.0",
|
||||
"sortablejs": "^1.15.0",
|
||||
"v-viewer": "^1.6.4",
|
||||
"vue": "2.6.10",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-contextmenujs": "^1.3.13",
|
||||
"vue-count-to": "^1.0.13",
|
||||
"vue-i18n": "^8.7.0",
|
||||
"vue-pdf": "^4.3.0",
|
||||
"vue-router": "3.0.6",
|
||||
"vue-seamless-scroll": "^1.1.21",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"vuex": "3.1.0",
|
||||
"webpack-aliyun-oss": "^0.5.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.0.0",
|
||||
"@babel/register": "7.0.0",
|
||||
"@vue/cli-plugin-babel": "3.6.0",
|
||||
"@vue/cli-plugin-eslint": "^3.9.1",
|
||||
"@vue/cli-plugin-unit-jest": "3.6.3",
|
||||
"@vue/cli-service": "3.6.0",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"autoprefixer": "^9.5.1",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "7.2.3",
|
||||
"babel-jest": "23.6.0",
|
||||
"chalk": "2.4.2",
|
||||
"connect": "3.6.6",
|
||||
"eslint": "5.15.3",
|
||||
"eslint-plugin-vue": "5.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"node-sass": "^4.9.0",
|
||||
"node-xlsx": "^0.21.0",
|
||||
"runjs": "^4.3.2",
|
||||
"sass-loader": "^7.1.0",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"script-loader": "0.7.2",
|
||||
"serve-static": "^1.13.2",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.2",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,420 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="clinicalDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
:disabled="type === 'look'"
|
||||
label-width="130px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="类型" prop="ClinicalQuestionType">
|
||||
<el-select v-model="form.ClinicalQuestionType" clearable @change="((val)=>{typeChange(val, form)})">
|
||||
<el-option
|
||||
v-for="item of $d.ClinicalQuestionType"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType === 'group'"
|
||||
label="分组名称"
|
||||
prop="GroupName"
|
||||
>
|
||||
<el-input v-model="form.GroupName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType === 'group'"
|
||||
label="分组名称(EN)"
|
||||
prop="GroupEnName"
|
||||
>
|
||||
<el-input v-model="form.GroupEnName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType !== 'group'"
|
||||
label="问题名称"
|
||||
prop="QuestionName"
|
||||
>
|
||||
<el-input v-model="form.QuestionName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType !== 'group'"
|
||||
label="问题名称(EN)"
|
||||
prop="QuestionEnName"
|
||||
>
|
||||
<el-input v-model="form.QuestionEnName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio'"
|
||||
label="选项"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.TypeValue"
|
||||
placeholder="选项请用‘|’分割多个选项"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group'" label="是否显示" prop="ShowQuestion">
|
||||
<el-radio-group
|
||||
v-model="form.ShowQuestion"
|
||||
@change="((val)=>{isShowQuestionChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ShowQuestion"
|
||||
:key="`ShowQuestion${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType !== 'group' && form.ShowQuestion===1"
|
||||
label="显示依赖父问题"
|
||||
prop="ParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`ParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 显示时依赖父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId && form.ShowQuestion===1" label="显示触发值" prop="ParentTriggerValue">
|
||||
<el-select v-model="form.ParentTriggerValue" clearable>
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value.toString()"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group' && form.ClinicalQuestionType !== 'table'" label="是否必填" prop="IsRequired">
|
||||
<el-radio-group
|
||||
v-model="form.IsRequired"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`QuestionRequired${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group'" label="问题分组">
|
||||
<el-select v-model="form.GroupId" clearable :disabled="isParentExistGroup">
|
||||
<el-option
|
||||
v-for="group of groupOptions"
|
||||
:key="group.GroupId"
|
||||
:label="group.GroupName"
|
||||
:value="group.GroupId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType === 'upload'" label="最大上传个数">
|
||||
<el-input-number v-model="form.ImageCount" controls-position="right" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
<el-form-item label="序号" prop="ShowOrder">
|
||||
<el-input-number
|
||||
v-model="form.ShowOrder"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateSystemClinicalQuestion, getSystemClinicalOtherQuestionList, getSystemClinicalGroupQuestionList } from '@/api/dictionary'
|
||||
export default {
|
||||
name: 'AddOrUpdateClinicalData',
|
||||
props: {
|
||||
clinicalId: {
|
||||
type: String,
|
||||
default() { return '' }
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default() { return '' }
|
||||
}
|
||||
},
|
||||
data() {
|
||||
var validateTypeVal = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error(this.$t('common:ruleMessage:specify')))
|
||||
} else {
|
||||
var arr = value.split('|')
|
||||
if (new Set(arr).size !== arr.length) {
|
||||
callback(new Error('选项不允许存在相同值'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
validateTypeVal: validateTypeVal,
|
||||
form: {
|
||||
Id: '',
|
||||
QuestionName: '',
|
||||
QuestionEnName: '',
|
||||
ClinicalQuestionType: null,
|
||||
ValueType: '',
|
||||
Unit: '',
|
||||
QuestionGenre: '',
|
||||
TypeValue: '',
|
||||
DictionaryCode: '',
|
||||
ParentId: '',
|
||||
ParentTriggerValue: '',
|
||||
ShowOrder: 0,
|
||||
ShowQuestion: 0,
|
||||
IsRequired: 2,
|
||||
IsJudgeQuestion: false,
|
||||
GroupName: '',
|
||||
GroupEnName: '',
|
||||
Remark: '',
|
||||
ImageCount: 1,
|
||||
RelevanceId: '',
|
||||
RelevanceValue: '',
|
||||
LesionType: '',
|
||||
QuestionType: null,
|
||||
IsShowInDicom: false,
|
||||
OrderMark: '',
|
||||
MaxQuestionCount: 0,
|
||||
GlobalReadingShowType: 3,
|
||||
DefaultValue: null,
|
||||
LimitEdit: 0,
|
||||
GroupId: null,
|
||||
ConvertShowType: 0
|
||||
},
|
||||
rules: {
|
||||
Type: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
LesionType: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
QuestionName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 300, message: '最大长度为 300' }],
|
||||
QuestionGenre: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
TypeValue: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 500, message: '最大长度为 500' }],
|
||||
DictionaryCode: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ShowQuestion: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
IsRequired: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentTriggerValue: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
RelevanceId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
RelevanceValue: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
GroupName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }]
|
||||
},
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
parentOptions: [],
|
||||
parentTriggerValOptions: [],
|
||||
groupOptions: [],
|
||||
isParentExistGroup: false,
|
||||
lesionTypes: [],
|
||||
dicList: [],
|
||||
CriterionDictionaryList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getGroupOptions()
|
||||
await this.getParentQuestions()
|
||||
await this.getBasicConfigSelect()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
if (this.form.ParentId !== '' && this.form.ParentId !== null && this.form.GroupName !== '') {
|
||||
this.isParentExistGroup = true
|
||||
}
|
||||
if (this.form.ParentId) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === this.form.ParentId
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.form.RelevanceId) {
|
||||
var i = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === this.form.RelevanceId
|
||||
})
|
||||
if (i !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.reParentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.reParentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.clinicalDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
if (this.form.ClinicalQuestionType !== 'upload') {
|
||||
this.form.ImageCount = 0
|
||||
}
|
||||
addOrUpdateSystemClinicalQuestion(this.form).then(res => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
getBasicConfigSelect() {
|
||||
this.dicList = this.$d
|
||||
},
|
||||
getGroupOptions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
SystemClinicalId: this.clinicalId
|
||||
}
|
||||
getSystemClinicalGroupQuestionList(param).then(res => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
getParentQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
SystemClinicalId: this.clinicalId
|
||||
}
|
||||
getSystemClinicalOtherQuestionList(param).then(res => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
typeChange(val, data) {
|
||||
if (val !== 'select' && val !== 'radio') {
|
||||
}
|
||||
if (val === 'table') {
|
||||
data.IsRequired = 2
|
||||
} else {
|
||||
data.LesionType = null
|
||||
}
|
||||
data.TypeValue = ''
|
||||
data.ValueType = ''
|
||||
data.Unit = ''
|
||||
},
|
||||
isShowQuestionChange(val, form) {
|
||||
if (val === 2) {
|
||||
form.IsRequired = 2
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
} else {
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
}
|
||||
},
|
||||
parentQuestionChange(val, form) {
|
||||
this.isParentExistGroup = false
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
var options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
if (this.parentOptions[index].GroupName) {
|
||||
this.isParentExistGroup = true
|
||||
form.GroupName = this.parentOptions[index].GroupName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
form.GroupName = ''
|
||||
form.GroupEnName = ''
|
||||
}
|
||||
form.ParentTriggerValue = ''
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,995 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:siteId')">
|
||||
<el-select v-model="searchData.SiteId" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="index"
|
||||
:label="item.TrialSiteCode"
|
||||
:value="item.SiteId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:subjectId')">
|
||||
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="访视/阅片期名称">
|
||||
<el-input
|
||||
v-model="searchData.TaskName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="阅片人">
|
||||
<el-select v-model="searchData.DoctorUserId" clearable style="width:120px;">
|
||||
<el-option v-for="item of DoctorUserList" :key="'DoctorUserId' + item.DoctorUserId" :value="item.DoctorUserId" :label="item.UserName" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="是否加急">
|
||||
<el-select v-model="searchData.IsUrgent" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="'IsUrgent' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务状态">
|
||||
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskState" :key="'TaskState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务类型">
|
||||
<el-select v-model="searchData.ReadingCategory" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ReadingCategory" :key="'ReadingCategory' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配状态">
|
||||
<el-select v-model="searchData.TaskAllocationState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskAllocationState" :key="'TaskAllocationState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配时间">
|
||||
<el-date-picker
|
||||
v-model="timeList"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="changeTimeList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.IsUrgent"
|
||||
:label="$t('trials:consistencyCheck:table:isUrgent')"
|
||||
show-overflow-tooltip
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.OriginalReReadingTask.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.OriginalReReadingTask.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.TaskCode"
|
||||
label="任务编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.TrialSiteCode"
|
||||
label="中心编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.SubjectCode"
|
||||
label="受试者编号"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.TaskName"
|
||||
label="访视/阅片期名称"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.CreateTime"
|
||||
label="任务创建时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.OriginalReReadingTask.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.OriginalReReadingTask.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.OriginalReReadingTask.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.OriginalReReadingTask.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.ReadingCategory"
|
||||
label="任务类型"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.OriginalReReadingTask.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.OriginalReReadingTask.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.OriginalReReadingTask.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.OriginalReReadingTask.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.ArmEnum"
|
||||
label="角色"
|
||||
min-width="80"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ArmEnum === 1" type="primary">{{ $fd('ArmEnum', scope.row.OriginalReReadingTask.ArmEnum) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ArmEnum === 2" type="success">{{ $fd('ArmEnum', scope.row.OriginalReReadingTask.ArmEnum) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ArmEnum === 3" type="info">{{ $fd('ArmEnum', scope.row.OriginalReReadingTask.ArmEnum) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ArmEnum === 4" type="danger">{{ $fd('ArmEnum', scope.row.OriginalReReadingTask.ArmEnum) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OriginalReReadingTask.ArmEnum === 5" type="warning">{{ $fd('ArmEnum', scope.row.OriginalReReadingTask.ArmEnum) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.UserName"
|
||||
label="阅片人"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.OriginalReReadingTask.UserName }}({{ scope.row.OriginalReReadingTask.FullName }})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.SignTime"
|
||||
label="阅片完成时间"
|
||||
min-width="180"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OriginalReReadingTask.RequestReReadingType"
|
||||
label="重阅申请类型"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.RequestReReadingType">
|
||||
<el-tag v-if="scope.row.RequestReReadingType === 2" type="danger">{{ $fd('RequestReReadingType', scope.row.RequestReReadingType) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('RequestReReadingType', scope.row.RequestReReadingType) }}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="RequestReReadingTime"
|
||||
label="申请时间"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="RequestReReadingReason"
|
||||
label="申请原因"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="AllocateTime"
|
||||
label="审批结果"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.RequestReReadingResultEnum">
|
||||
<el-tooltip v-if="scope.row.RequestReReadingResultEnum === 2" class="item" effect="dark" placement="top">
|
||||
<div slot="content">
|
||||
{{ scope.row.RequestReReadingRejectReason }}
|
||||
</div>
|
||||
<el-tag type="danger">{{ $fd('RequestReReadingResult', scope.row.RequestReReadingResultEnum) }}</el-tag>
|
||||
</el-tooltip>
|
||||
<el-tag v-else type="primary">{{ $fd('RequestReReadingResult', scope.row.RequestReReadingResultEnum) }}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ReReadingNewTaskCode"
|
||||
label="新任务编号"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="210"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
:disabled="!!scope.row.RequestReReadingResultEnum || scope.row.RequestReReadingType === 1"
|
||||
icon="el-icon-check"
|
||||
circle
|
||||
title="同意"
|
||||
@click="openReReadingOrBackList(scope.row,1)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="!!scope.row.RequestReReadingResultEnum || scope.row.RequestReReadingType === 1"
|
||||
icon="el-icon-close"
|
||||
circle
|
||||
title="拒绝"
|
||||
@click="confirmReReading(scope.row,2, true)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<el-dialog
|
||||
v-if="ConfirmReReadingVisible"
|
||||
title="驳回"
|
||||
:visible.sync="ConfirmReReadingVisible"
|
||||
width="600px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div style="padding:10px;border: 1px solid #e0e0e0;max-height:650px;overflow-y: auto;">
|
||||
<el-form
|
||||
ref="reasonForm"
|
||||
:rules="rules"
|
||||
:model="ConfirmReReadingForm"
|
||||
class="demo-ruleForm"
|
||||
size="small"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="驳回原因" prop="RequestReReadingRejectReason">
|
||||
<el-input
|
||||
v-model="ConfirmReReadingForm.RequestReReadingRejectReason"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:placeholder="$t('common:ruleMessage:specify')"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ConfirmReReadingVisible = false;ConfirmReReadingForm = { RequestReReadingRejectReason: null }">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="confirmReReading(rowData, 2)">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ReReadingOrBackVisible"
|
||||
title="重阅影响任务列表"
|
||||
:visible.sync="ReReadingOrBackVisible"
|
||||
width="1360px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="InfluenceTaskList"
|
||||
stripe
|
||||
height="100"
|
||||
style="min-height: 400px;"
|
||||
>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="任务编号"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
label="中心编号"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="受试者编号"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="VisitTaskNum"
|
||||
label="访视/阅片期名称"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.TaskName}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
min-width="100"
|
||||
label="任务类型"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OptType"
|
||||
label="生效后任务状态"
|
||||
min-width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.OptType === 0" type="primary">{{ $fd('TaskState', scope.row.OptType) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OptType === 1" type="info">{{ $fd('TaskState', scope.row.OptType) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OptType === 3" type="danger">{{ $fd('TaskState', scope.row.OptType) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OptType === 4" type="warning">{{ $fd('TaskState', scope.row.OptType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片人"
|
||||
min-width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-if="scope.row.DoctorUser.UserName" slot-scope="scope">
|
||||
{{ scope.row.DoctorUser.UserName }}({{ scope.row.DoctorUser.FullName }})
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ReReadingOrBackVisible = false">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="confirmReReading(rowData, 1)">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getTrialSiteSelect } from '@/api/trials'
|
||||
import { getReReadingOrBackInfluenceTaskList, applyReReading, confirmReReading, getSPMReReadingTaskList, assignSubjectTaskToDoctor, manualAssignDoctorApplyTask, autoSubjectAssignDoctor, getTaskAllocationRuleList, getSubjectAssignList, assignSubjectDoctor, cancelSubjectAssignDoctor, deleteTaskAllocationRule, configTrialTaskInfo, getDoctorUserSelectList } from '@/api/trials/reading'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
IsUrgent: null,
|
||||
TaskName: null,
|
||||
TaskState: null,
|
||||
DoctorUserId: null,
|
||||
ReadingCategory: null,
|
||||
TaskAllocationState: null,
|
||||
BeginAllocateDate: null,
|
||||
EndAllocateDate: null,
|
||||
RootReReadingTaskId: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialsNotice',
|
||||
components: { BaseContainer, Pagination },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
ReReadingOrBackVisible: false,
|
||||
InfluenceTaskList: [],
|
||||
maxLength: 0,
|
||||
list: [],
|
||||
siteOptions: [],
|
||||
total: 0,
|
||||
SubjectAssignListTotal: 0,
|
||||
loading: false,
|
||||
AllocationConfigVisible: false,
|
||||
ConfirmReReadingForm: {
|
||||
RequestReReadingRejectReason: null
|
||||
},
|
||||
rules: {
|
||||
RequestReReadingRejectReason: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }]
|
||||
},
|
||||
ConfirmReReadingVisible: false,
|
||||
taskAllocationRuleVisible: false,
|
||||
AutoAlloctionVisible: false,
|
||||
manualAllocationVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
currentData: {},
|
||||
param: {},
|
||||
DoctorUserList: [],
|
||||
TaskAllocationRuleList: [],
|
||||
btnLoading: false,
|
||||
value: true,
|
||||
value1: true,
|
||||
TrialTaskInfo: {
|
||||
TrialId: null,
|
||||
TaskAllocateObjEnum: 0,
|
||||
FollowVisitAutoAssignDefaultState: 0,
|
||||
FollowGlobalVisitAutoAssignDefaultState: 0,
|
||||
TaskAllocateDefaultState: 1
|
||||
},
|
||||
title: '',
|
||||
rowData: {},
|
||||
timeList: [],
|
||||
SubjectAssignList: [],
|
||||
SubjectAssignSelectList: [],
|
||||
TaskAllocationRuleSelectList: [],
|
||||
readVisible: false,
|
||||
TaskOptType: null,
|
||||
OtherInfo: null,
|
||||
ReadingType: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$route.query.SiteId) {
|
||||
this.searchData.SiteId = this.$route.query.SiteId
|
||||
this.searchData.SubjectCode = this.$route.query.SubjectCode
|
||||
this.searchData.TaskName = this.$route.query.TaskName
|
||||
this.searchData.DoctorUserId = this.$route.query.DoctorUserId
|
||||
changeURLStatic('SiteId', '')
|
||||
changeURLStatic('SubjectCode', '')
|
||||
changeURLStatic('TaskName', '')
|
||||
changeURLStatic('DoctorUserId', '')
|
||||
}
|
||||
this.getList()
|
||||
this.getSite()
|
||||
this.getDoctorUserSelectList()
|
||||
},
|
||||
methods: {
|
||||
openReReadingOrBackList(row) {
|
||||
this.loading = true
|
||||
this.rowData = {...row}
|
||||
getReReadingOrBackInfluenceTaskList(row.OriginalReReadingTaskId, true, row.Id).then(res => {
|
||||
this.InfluenceTaskList = res.Result
|
||||
this.ReReadingOrBackVisible = true
|
||||
this.loading = false
|
||||
}).catch(() => {this.loading = false})
|
||||
},
|
||||
lookReadingResults(row) {
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/noneDicomReading?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.NewReReadingTaskId}&TokenKey=${token}`
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
// 申请重阅
|
||||
applyReReading(row) {
|
||||
this.$confirm('确定要申请重阅?').then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
TaskIdList: [
|
||||
row.NewReReadingTaskId
|
||||
],
|
||||
TrialId: this.$route.query.trialId,
|
||||
RequestReReadingType: 2,
|
||||
RequestReReadingReason: ''
|
||||
}
|
||||
applyReReading(params).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('申请重阅成功')
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
confirmReReading(row, type, open) {
|
||||
if (open) {
|
||||
this.rowData = { ...row }
|
||||
this.ConfirmReReadingVisible = true
|
||||
this.ConfirmReReadingForm = {
|
||||
RequestReReadingRejectReason: null
|
||||
}
|
||||
return
|
||||
}
|
||||
if (type === 2) {
|
||||
this.$refs.reasonForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
var params = {
|
||||
ConfirmReReadingList: [
|
||||
{
|
||||
Id: row.Id,
|
||||
OriginalReReadingTaskId: row.OriginalReReadingTaskId,
|
||||
RootReReadingTaskId: row.RootReReadingTaskId,
|
||||
NewReReadingTaskId: row.NewReReadingTaskId
|
||||
}
|
||||
],
|
||||
RequestReReadingRejectReason: this.ConfirmReReadingForm.RequestReReadingRejectReason,
|
||||
TrialId: this.$route.query.trialId,
|
||||
RequestReReadingResultEnum: type
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
confirmReReading(params).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success(`${type === 1 ? '同意' : '拒绝'}申请成功`)
|
||||
this.getList()
|
||||
this.ConfirmReReadingVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$confirm(`确定${type === 1 ? '同意' : '拒绝'}该重阅申请?`).then(() => {
|
||||
var params = {
|
||||
ConfirmReReadingList: [
|
||||
{
|
||||
Id: row.Id,
|
||||
OriginalReReadingTaskId: row.OriginalReReadingTaskId,
|
||||
RootReReadingTaskId: row.RootReReadingTaskId,
|
||||
NewReReadingTaskId: row.NewReReadingTaskId
|
||||
}
|
||||
],
|
||||
TrialId: this.$route.query.trialId,
|
||||
RequestReReadingResultEnum: type
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
confirmReReading(params).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success(`${type === 1 ? '同意' : '拒绝'}申请成功`)
|
||||
this.ReReadingOrBackVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
assignSubjectTaskToDoctor(row, type) {
|
||||
this.rowData = { ...row }
|
||||
this.rowData.TaskOptType = type
|
||||
if (type === 1 || type === 2) {
|
||||
this.readVisible = true
|
||||
} else if (type === 3) {
|
||||
this.$confirm('是否确定分配').then(() => {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
} else if (type === 4) {
|
||||
this.$confirm('是否确定取消分配').then(() => {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
assignSubjectTaskToDoctorSave() {
|
||||
this.$refs.readDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(() => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
manualAssignDoctorApplyTask(row) {
|
||||
console.log(row)
|
||||
var params = {
|
||||
TrialId: this.trialId
|
||||
}
|
||||
if (row) {
|
||||
params.SubjectDoctorUserList = [
|
||||
row
|
||||
]
|
||||
}
|
||||
this.$confirm('确定将当前已分配阅片人应用到任务?').then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
manualAssignDoctorApplyTask(params).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('应用成功')
|
||||
this.getList()
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
autoSubjectAssignDoctor() {
|
||||
this.$confirm('确定执行自动分配?').then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
autoSubjectAssignDoctor({ TrialId: this.trialId }).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('自动分配成功')
|
||||
this.getList()
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSaveTaskAllocationRuleSelectList() {
|
||||
if (this.TaskAllocationRuleSelectList.length === 0) {
|
||||
this.$message.error('请选择阅片人')
|
||||
return
|
||||
}
|
||||
var num
|
||||
if (this.ReadingType === 2) {
|
||||
num = 2
|
||||
} else {
|
||||
num = 1
|
||||
}
|
||||
if (this.TaskAllocationRuleSelectList.length !== num) {
|
||||
this.$message.error(`当前阅片模式为${this.$fd('ReadingMethod', this.ReadingType)},请选择正确阅片人数量`)
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
DoctorUserIdArmList: this.TaskAllocationRuleSelectList.map((v, i) => { return { DoctorUserId: v.DoctorUserId, ArmEnum: this.ReadingType === 1 ? 1 : i + 1 } }),
|
||||
SubjectIdList: this.SubjectAssignSelectList.map(v => v.SubjectId),
|
||||
TrialId: this.trialId,
|
||||
IsReAssign: true
|
||||
}
|
||||
assignSubjectDoctor(params).then(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.openAutoAlloction()
|
||||
this.TaskAllocationRuleSelectList = []
|
||||
this.SubjectAssignSelectList = []
|
||||
this.getDoctorUserSelectList()
|
||||
this.$message.success('分配成功')
|
||||
this.manualAllocationVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
selectable(row) {
|
||||
var num
|
||||
if (this.ReadingType === 2) {
|
||||
num = 2
|
||||
} else {
|
||||
num = 1
|
||||
}
|
||||
if (this.TaskAllocationRuleSelectList.length === num && !this.TaskAllocationRuleSelectList.find(v => { return v.UserName === row.UserName })) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
cancelSubjectAssignDoctor(row) {
|
||||
if (row) {
|
||||
this.$confirm('确定要清空该受试者的阅片人吗?').then(() => {
|
||||
var params = {
|
||||
SubjectIdList: [row.SubjectId],
|
||||
TrialId: this.trialId
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
cancelSubjectAssignDoctor(params).then(() => {
|
||||
this.$message.success('清空成功')
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.SubjectAssignSelectList.length === 0) {
|
||||
this.$message.error('请勾选要清空阅片人的受试者')
|
||||
return
|
||||
}
|
||||
this.$confirm('确定要清空该受试者的阅片人吗?').then(() => {
|
||||
var params = {
|
||||
SubjectIdList: this.SubjectAssignSelectList.map(v => v.SubjectId),
|
||||
TrialId: this.trialId
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
cancelSubjectAssignDoctor(params).then(() => {
|
||||
this.$message.success('清空成功')
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
manualAllocation(row) {
|
||||
if (row) {
|
||||
this.SubjectAssignSelectList = [row]
|
||||
}
|
||||
if (this.SubjectAssignSelectList.length === 0) {
|
||||
this.$message.error('请勾选要分配的受试者')
|
||||
return
|
||||
}
|
||||
this.manualAllocationVisible = true
|
||||
},
|
||||
handleTaskAllocationRuleListSelectChange(e) {
|
||||
this.TaskAllocationRuleSelectList = e
|
||||
},
|
||||
handleSubjectAssignListSelectChange(e) {
|
||||
this.SubjectAssignSelectList = e
|
||||
},
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
this.searchData.BeginAllocateDate = this.timeList[0]
|
||||
this.searchData.EndAllocateDate = this.timeList[1]
|
||||
} else {
|
||||
this.searchData.BeginAllocateDate = null
|
||||
this.searchData.EndAllocateDate = null
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
this.AllocationConfigVisible = false
|
||||
},
|
||||
handleSave() {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.TrialTaskInfo)
|
||||
params.TrialId = this.$route.query.trialId
|
||||
configTrialTaskInfo(params).then(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.AllocationConfigVisible = false
|
||||
this.getList()
|
||||
this.$message.success('保存成功')
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除${row.UserName}的任务分配规则?`, {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}).then(() => {
|
||||
this.loading = true
|
||||
deleteTaskAllocationRule(row.Id).then(() => {
|
||||
this.loading = false
|
||||
this.$message.success('删除成功')
|
||||
this.openAllocationConfigVisible()
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
addOrEdit(row) {
|
||||
if (row) {
|
||||
this.rowData = { ...row }
|
||||
this.title = '编辑'
|
||||
} else {
|
||||
this.rowData = {}
|
||||
this.title = '新增'
|
||||
}
|
||||
this.taskAllocationRuleVisible = true
|
||||
},
|
||||
openAllocationConfigVisible() {
|
||||
this.loading = true
|
||||
getTaskAllocationRuleList({
|
||||
TrialId: this.$route.query.trialId
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.TaskAllocationRuleList = res.Result
|
||||
this.TrialTaskInfo = Object.assign({}, res.OtherInfo)
|
||||
this.AllocationConfigVisible = true
|
||||
this.taskAllocationRuleVisible = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
openAutoAlloction() {
|
||||
this.loading = true
|
||||
getTaskAllocationRuleList({
|
||||
TrialId: this.$route.query.trialId
|
||||
}).then(async(res) => {
|
||||
this.taskSearchData.TrialId = this.$route.query.trialId
|
||||
var params = Object.assign({}, this.taskSearchData)
|
||||
var SubjectAssignListRes = await getSubjectAssignList(params)
|
||||
this.SubjectAssignList = SubjectAssignListRes.Result.CurrentPageData
|
||||
this.SubjectAssignListTotal = SubjectAssignListRes.Result.TotalCount
|
||||
this.loading = false
|
||||
this.TaskAllocationRuleList = res.Result
|
||||
this.TrialTaskInfo = Object.assign({}, res.OtherInfo)
|
||||
this.AutoAlloctionVisible = true
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getDoctorUserSelectList() {
|
||||
getDoctorUserSelectList(this.$route.query.trialId).then(res => {
|
||||
this.DoctorUserList = res.Result
|
||||
if (this.DoctorUserList.length > 0) {
|
||||
this.ReadingType = this.DoctorUserList[0].ReadingType
|
||||
} else {
|
||||
this.$alert('请先去选择项目阅片人')
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getSPMReReadingTaskList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.OtherInfo = res.OtherInfo
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
getSite() {
|
||||
getTrialSiteSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.hidden-row{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-dialog__body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
>>>.el-tag--danger.el-tag--dark {
|
||||
// background-color: #f56c6c!important;
|
||||
border-color: none!important;
|
||||
// color: #fff!important;
|
||||
}
|
||||
>>>#TaskAllocationRuleList thead .el-checkbox__inner{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-descriptions-item__label.has-colon:after{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,214 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="search-form" style="display:flex;justify-content: space-between;">
|
||||
<div>
|
||||
</div>
|
||||
<div>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
style="margin-right: 10px;"
|
||||
>
|
||||
配置
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:0}"
|
||||
height="100"
|
||||
style="width: 100%"
|
||||
:data="list"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="序号"
|
||||
width="50"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.$index + 1}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Code"
|
||||
label="键值"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ValueCN"
|
||||
label="中文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Value"
|
||||
label="英文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Description"
|
||||
label="描述"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-dialog
|
||||
v-if="config.visible"
|
||||
:visible.sync="config.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="config.title"
|
||||
width="90%"
|
||||
append-to-body
|
||||
>
|
||||
<div>
|
||||
<div style="text-align: right;">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleSave"
|
||||
v-loading="loading"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:100}"
|
||||
height="100"
|
||||
ref="multipleTable"
|
||||
:data="$d[parentCode]"
|
||||
stripe
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.Code"
|
||||
label="键值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.ValueCN"
|
||||
label="中文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.Value"
|
||||
label="英文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.Description"
|
||||
label="描述"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAssessType, setCriterionDictionary, setDictionaryBaseLineUse, setDictionaryFollowVisitUse } from '@/api/dictionary'
|
||||
export default {
|
||||
props: {
|
||||
criterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
parentCode: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
rowData: {},
|
||||
activeName: '0',
|
||||
addOrEdit: { visible: false, title: '' },
|
||||
preview: { visible: false, title: 'eCRF预览' },
|
||||
config: { visible: false, title: '标准字典值' },
|
||||
selectedList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
console.log(this.$d[this.parentCode])
|
||||
},
|
||||
methods: {
|
||||
toggleSelection(rows) {
|
||||
console.log(this.$refs.multipleTable)
|
||||
if (rows) {
|
||||
rows.forEach(row => {
|
||||
this.$refs.multipleTable.toggleRowSelection(row);
|
||||
});
|
||||
} else {
|
||||
this.$refs.multipleTable.clearSelection();
|
||||
}
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.selectedList = val
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
getAssessType({
|
||||
CriterionId: this.criterionId,
|
||||
ParentCode: this.parentCode
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result
|
||||
})
|
||||
},
|
||||
handleAdd() {
|
||||
this.config.visible = true
|
||||
this.$nextTick(() => {
|
||||
var a = this.$d[this.parentCode].filter(v => {
|
||||
return !!this.list.find(v1 => {
|
||||
return v1.DictionaryId === v.id
|
||||
})
|
||||
})
|
||||
this.toggleSelection(a)
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.loading = true
|
||||
var params = {
|
||||
CriterionId: this.criterionId,
|
||||
ParentCode: this.parentCode,
|
||||
DictionaryIds: this.selectedList.map(v => v.id),
|
||||
isSystemCriterion: true
|
||||
}
|
||||
setCriterionDictionary(params).then(res => {
|
||||
this.loading = false
|
||||
this.$message.success('保存成功')
|
||||
this.config.visible = false
|
||||
this.selectedList = []
|
||||
this.getList()
|
||||
this.$emit('getList')
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
handleDelete() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
>>>.el-form-item__content{
|
||||
width: calc(100% - 110px);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,133 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form-item
|
||||
v-if="(questionForm[question.ParentId] === question.ParentTriggerValue) || question.ParentId===''||question.ParentId===null"
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.ReadingQuestionTrialId"
|
||||
:rules="[
|
||||
{ required: question.IsRequired && question.Type!=='group' && question.Type!=='summary',
|
||||
message: '请注明', trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group'?'mb':'']"
|
||||
>
|
||||
<div
|
||||
v-if="question.Type==='group'"
|
||||
style="font-weight: bold;font-size: 16px;"
|
||||
>
|
||||
{{ question.GroupName }}
|
||||
</div>
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.ReadingQuestionTrialId]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.ReadingQuestionTrialId]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="question.Type==='select'"
|
||||
v-model="questionForm[question.ReadingQuestionTrialId]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.ReadingQuestionTrialId]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-radio v-for="val in question.TypeValue.split('|')" :key="val" :label="val">{{ val }}</el-radio>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.ReadingQuestionTrialId]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
>
|
||||
<el-checkbox v-for="val in question.TypeValue.split('|')" :key="val" :label="val">{{ val }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<FormItem
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.ReadingQuestionTrialId"
|
||||
:question="item"
|
||||
:reading-task-state="readingTaskState"
|
||||
:question-form="questionForm"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'FormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
// console.log(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.ReadingQuestionTrialId)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,272 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<div style="padding: 0 20px;">
|
||||
<div class="info-content" v-html="crcMessageInfo.TalkContent" />
|
||||
</div>
|
||||
<div>
|
||||
<div style="padding: 10px;background: #f3f3f3;border-radius: 10px;margin-top: 10px">
|
||||
<div style="display:flex;margin-bottom: 10px;justify-content: space-between;align-items: center">
|
||||
<div>
|
||||
请准确核实后录入当前访视的实际影像检查记录:
|
||||
</div>
|
||||
<el-button type="primary" size="mini" @click="addMsg">添加</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="msgList">
|
||||
<el-table-column type="index" width="40" />
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="检查日期"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.StudyDate}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="检查类型"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.Modality}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="已提交"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{$fd('YesOrNo', scope.row.IsJoin)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="实际存在"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
:disabled="!scope.row.IsJoin"
|
||||
v-model="scope.row.IsCheck"
|
||||
@change="compareStudy"
|
||||
>
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
width="100px"
|
||||
label="操作"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button :disabled="scope.row.IsJoin" @click="moveMsg(scope.$index)" size="small" type="text">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form ref="revenusForm"
|
||||
size="small"
|
||||
label-width="400px"
|
||||
:label-position="'top'"
|
||||
:rules="rules"
|
||||
:model="form">
|
||||
<el-form-item v-if="isLackOf" label="IRC与实际情况影像检查不一致的原因为:" prop="reason">
|
||||
<el-checkbox-group v-model="form.reason" style="display: flex;flex-direction: column">
|
||||
<el-checkbox style="display: block" label="EDC按疗效评估数据记录影像检查信息;">EDC按疗效评估数据记录影像检查信息</el-checkbox>
|
||||
<el-checkbox style="display: block" label="EDC录入错误;">EDC录入错误</el-checkbox>
|
||||
<el-checkbox style="display: block" label="IRC数据上传错误,申请回退并重新上传;">IRC数据上传错误,申请回退并重新上传</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="function">
|
||||
<!-- 发送 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleReply"
|
||||
>
|
||||
{{ $t('trials:consistencyCheck:button:sendMessage') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-if="studyVisible"
|
||||
:visible.sync="studyVisible"
|
||||
v-dialogDrag
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
:width="'500px'"
|
||||
title="添加检查"
|
||||
>
|
||||
<el-form>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label-width="80px" label="检查日期">
|
||||
<el-date-picker
|
||||
v-model="typeInfo.StudyDate"
|
||||
style="width: 100%"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="80px" label="检查类型">
|
||||
<el-select
|
||||
v-model="typeInfo.Modality"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="item of $d.Modality" :label="item.raw.Value" :value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button size="small" type="primary" @click="handleCancel"> {{ $t('common:button:cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'CrcSendMessage',
|
||||
props: {
|
||||
crcMessageInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
TalkContent: null,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
msgList: [],
|
||||
studyVisible: false,
|
||||
typeInfo: {
|
||||
StudyDate: null,
|
||||
Modality: null,
|
||||
IsJoin: false,
|
||||
IsCheck: true
|
||||
},
|
||||
isLackOf: false,
|
||||
EDCList: [],
|
||||
IRCList: [],
|
||||
form: {
|
||||
reason: []
|
||||
},
|
||||
rules: {
|
||||
reason: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.crcMessageInfo.ParamInfoList.forEach(v => {
|
||||
this.msgList.push({...v, IsJoin: true, Ischeck: false})
|
||||
})
|
||||
this.compareStudy()
|
||||
},
|
||||
methods: {
|
||||
compareStudy() {
|
||||
var isLackOf = false
|
||||
this.IRCList = []
|
||||
this.msgList.forEach(v => {
|
||||
if (v.IsJoin !== v.IsCheck) {
|
||||
isLackOf = true
|
||||
this.IRCList.push(v)
|
||||
}
|
||||
})
|
||||
this.isLackOf = isLackOf
|
||||
},
|
||||
handleCancel() {
|
||||
this.studyVisible = false
|
||||
this.typeInfo = {
|
||||
StudyDate: null,
|
||||
Modality: null
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
if (!this.typeInfo.StudyDate || !this.typeInfo.Modality) {
|
||||
this.$message.error('请选择检查日期和检查类型')
|
||||
return
|
||||
}
|
||||
this.msgList.push({...this.typeInfo})
|
||||
this.compareStudy()
|
||||
this.studyVisible = false
|
||||
this.typeInfo = {
|
||||
StudyDate: null,
|
||||
Modality: null,
|
||||
IsJoin: false,
|
||||
IsCheck: true
|
||||
}
|
||||
},
|
||||
closeLoading() {
|
||||
this.loading = false
|
||||
},
|
||||
addMsg() {
|
||||
this.studyVisible = true
|
||||
},
|
||||
moveMsg(index) {
|
||||
this.$confirm('确定删除该条检查记录?').then(res => {
|
||||
this.msgList.splice(index, 1)
|
||||
this.compareStudy()
|
||||
})
|
||||
},
|
||||
handleReply() {
|
||||
if (this.msgList.length === 0) {
|
||||
this.$message.error('请录入真实的检查情况')
|
||||
return
|
||||
}
|
||||
this.$refs.revenusForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
var TalkContent = ''
|
||||
TalkContent += '经核实,该受试者当前访视的实际影像检查如下:<br>'
|
||||
this.msgList.forEach((v, i) => {
|
||||
TalkContent += `${i+1}.${v.StudyDate}的${v.Modality}影像检查<br>`
|
||||
})
|
||||
if (this.isLackOf) {
|
||||
TalkContent += '<br>'
|
||||
TalkContent += 'IRC与实际情况不一致影像检查如下:<br>'
|
||||
this.IRCList.forEach((v, i) => {
|
||||
TalkContent += `${i+1}.${v.StudyDate}的${v.Modality}影像检查(${v.IsJoin && !v.IsCheck ? 'IRC多余': 'IRC缺少'})<br>`
|
||||
})
|
||||
if (this.form.reason.length > 0) {
|
||||
TalkContent += '<br>'
|
||||
TalkContent += 'IRC与实际情况影像检查不一致的原因为:<br>'
|
||||
this.form.reason.forEach((v, i) => {
|
||||
TalkContent += `${i+1}.${v}<br>`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
TalkContent += `<br>IRC与实际情况影像检查一致`
|
||||
}
|
||||
console.log(TalkContent)
|
||||
this.$emit('sendMessage', TalkContent, this.closeLoading)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.function{
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
>>>.el-form--label-top .el-form-item__label{
|
||||
padding-bottom: 0;
|
||||
padding-top: 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,33 @@
|
|||
const getDefaultState = () => {
|
||||
return {
|
||||
reviewersQuery: null,
|
||||
isEnglish: true
|
||||
}
|
||||
}
|
||||
const state = getDefaultState
|
||||
|
||||
const mutations = {
|
||||
RESET_STATE: (state) => {
|
||||
Object.assign(state, getDefaultState())
|
||||
},
|
||||
SET_QUERYPARAM: (state, query) => {
|
||||
state.reviewersQuery = query
|
||||
},
|
||||
SET_ISENGLISH: (state, isEnglish) => {
|
||||
state.isEnglish = isEnglish
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
resetState({ commit }) {
|
||||
commit('RESET_STATE')
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="clinicalDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
label-width="110px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="类型" prop="Type">
|
||||
<el-select v-model="form.Type">
|
||||
<el-option
|
||||
v-for="item of $d.Criterion_Question_Type"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type === 'group'"
|
||||
label="分组名称"
|
||||
prop="GroupName"
|
||||
>
|
||||
<el-input v-model="form.GroupName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group'"
|
||||
label="审核问题"
|
||||
prop="QuestionName"
|
||||
>
|
||||
<el-input v-model="form.QuestionName" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'textarea' && form.Type !== 'input' && form.Type !== 'group' && form.Type !== 'summary'"
|
||||
label="选项"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input v-model="form.TypeValue" placeholder="选项请用‘|’分割多个选项" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 父问题 -->
|
||||
<el-form-item v-if="form.Type !== 'group'" label="父问题">
|
||||
<el-select v-model="form.ParentId" clearable @change="((val)=>{parentQuestionChange(val, form)})">
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="item.QuestionId"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId" label="父问题触发值" prop="ParentTriggerValue">
|
||||
<el-select v-model="form.ParentTriggerValue">
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="问题分组">
|
||||
<el-select v-model="form.GroupName" clearable :disabled="isParentExistGroup">
|
||||
<el-option
|
||||
v-for="group of groupOptions"
|
||||
:key="group"
|
||||
:label="group"
|
||||
:value="group"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="是否必填">
|
||||
<el-radio-group v-model="form.IsRequired">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="是否裁判问题">
|
||||
<el-radio-group v-model="form.IsJudgeQuestion">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="注释">
|
||||
<el-input v-model="form.Remark" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="启用状态: ">
|
||||
<el-radio-group v-model="form.IsEnable">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item label="序号: " prop="ShowOrder">
|
||||
<el-input-number v-model="form.ShowOrder" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateReadingQuestionTrial, getTrialCriterionOtherQuestion, getTrialGroupNameList } from '@/api/trials'
|
||||
export default {
|
||||
name: 'AddOrUpdateClinicalData',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
Id: '',
|
||||
ReadingQuestionCriterionTrialId: '',
|
||||
QuestionName: '',
|
||||
Type: 'select',
|
||||
TypeValue: '',
|
||||
ParentId: '',
|
||||
ParentTriggerValue: '',
|
||||
ShowOrder: 0,
|
||||
IsRequired: true,
|
||||
IsJudgeQuestion: false,
|
||||
GroupName: '',
|
||||
Remark: ''
|
||||
// IsEnable: true
|
||||
},
|
||||
rules: {
|
||||
Type: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
QuestionName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }],
|
||||
TypeValue: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 200, message: '最大长度为 200' }],
|
||||
ParentTriggerValue: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
GroupName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }]
|
||||
},
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
parentOptions: [],
|
||||
parentTriggerValOptions: [],
|
||||
groupOptions: [],
|
||||
isParentExistGroup: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getGroupOptions()
|
||||
await this.getParentQuestions()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
if (this.form.ParentId !== '' && this.form.ParentId !== null && this.form.GroupName !== '') {
|
||||
this.isParentExistGroup = true
|
||||
}
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.clinicalDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
addOrUpdateReadingQuestionTrial(this.form).then(res => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
getGroupOptions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
criterionId: this.data.ReadingQuestionCriterionTrialId
|
||||
}
|
||||
getTrialGroupNameList(param).then(res => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
getParentQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
ReadingQuestionCriterionTrialId: this.data.ReadingQuestionCriterionTrialId,
|
||||
id: this.data.Id
|
||||
}
|
||||
getTrialCriterionOtherQuestion(param).then(res => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
parentQuestionChange(val, form) {
|
||||
this.isParentExistGroup = false
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.parentTriggerValOptions = this.parentOptions[index].TypeValue.split('|')
|
||||
if (this.parentOptions[index].GroupName) {
|
||||
this.isParentExistGroup = true
|
||||
form.GroupName = this.parentOptions[index].GroupName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
form.ParentTriggerValue = ''
|
||||
form.GroupName = ''
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,140 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="sign-form-wrapper">
|
||||
<div class="sign-form-body">
|
||||
<h4 v-if="signText" style="color:red;white-space: pre-line;">* {{ signText }}</h4>
|
||||
<el-form
|
||||
ref="signForm"
|
||||
:model="signForm"
|
||||
size="small"
|
||||
label-width="100px"
|
||||
>
|
||||
<!-- 用户名 -->
|
||||
<el-form-item
|
||||
:label="$t('common:form:sign:userName')"
|
||||
prop="userName"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input v-model="signForm.userName" />
|
||||
</el-form-item>
|
||||
<!-- 密码 -->
|
||||
<el-form-item
|
||||
:label="$t('common:form:sign:password')"
|
||||
prop="password"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input v-model="signForm.password" show-password auto-complete="new-password" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer sign-form-footer">
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleclose">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button :loading="btnLoading" :disabled="unsigned" size="small" type="primary" @click="handleVerifySignature">
|
||||
{{ $t('common:button:sign') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import { verifySignature } from '@/api/trials'
|
||||
import md5 from 'js-md5'
|
||||
// import const_ from '@/const/sign-code'
|
||||
export default {
|
||||
name: 'SignForm',
|
||||
props: {
|
||||
signCodeEnum: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
subjectVisitId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
signForm: {
|
||||
userName: '',
|
||||
password: ''
|
||||
},
|
||||
signText: '',
|
||||
signCodeId: '',
|
||||
signCode: '',
|
||||
btnLoading: false,
|
||||
loading: false,
|
||||
unsigned: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loading = true
|
||||
this.$store.dispatch('trials/getSignInfo', { signCode: this.signCodeEnum })
|
||||
.then((res) => {
|
||||
this.unsigned = false
|
||||
this.loading = false
|
||||
this.signText = res.SignText
|
||||
this.signCode = res.SignCode
|
||||
this.signCodeId = res.SignCodeId
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.unsigned = true
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleVerifySignature() {
|
||||
const currentUser = zzSessionStorage.getItem('userName').toLocaleLowerCase()
|
||||
this.$refs.signForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
if (this.signForm.userName.trim().toLocaleLowerCase() !== currentUser) {
|
||||
// 用户名输入错误!
|
||||
this.$alert(this.$t('common:message:signWarning'))
|
||||
this.loading = false
|
||||
return
|
||||
}
|
||||
this.btnLoading = true
|
||||
const param = {
|
||||
UserName: this.signForm.userName,
|
||||
PassWord: md5(this.signForm.password),
|
||||
TrialId: this.$route.query.trialId,
|
||||
SignCode: this.signCode,
|
||||
SignText: this.signText,
|
||||
SignCodeId: this.signCodeId,
|
||||
SubjectVisitId: this.subjectVisitId
|
||||
}
|
||||
this.$emit('closeDialog', true, param)
|
||||
})
|
||||
},
|
||||
handleclose() {
|
||||
this.$emit('closeDialog', false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.sign-form-wrapper{
|
||||
.sign-form-body{
|
||||
padding:5px 10px 10px 10px;
|
||||
// border: 1px solid #e0e0e0;
|
||||
max-height:650px;
|
||||
overflow-y: auto;
|
||||
// >>>.el-form-item__label{
|
||||
// color: #fff;
|
||||
// }
|
||||
}
|
||||
.sign-form-footer{
|
||||
padding:10px;
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
.el-dialog__body .sign-form-body h4{
|
||||
word-break: normal!important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,449 @@
|
|||
<template>
|
||||
<box-content v-loading="loading" style="height: 100%;background: #fff;">
|
||||
<!-- 搜索框 -->
|
||||
<div class="search">
|
||||
<el-form
|
||||
:inline="true"
|
||||
class="base-search-form"
|
||||
>
|
||||
<!-- 审核问题 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:qcCfg:table:questionName')"
|
||||
>
|
||||
<el-input
|
||||
v-model="searchData.QuestionName"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 类型 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:qcCfg:table:type')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.Type"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.QcType"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('trials:qcCfg:table:isEnable')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.IsEnable"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.IsEnable"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('trials:qcCfg:table:isRequired')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.IsRequired"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsRequired${item.value}`"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-search"
|
||||
@click="handleSearch"
|
||||
>
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="handleReset"
|
||||
>
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto">
|
||||
<el-button
|
||||
:disabled="otherInfo.QuestionCount===0"
|
||||
type="primary"
|
||||
icon="el-icon-view"
|
||||
@click="preview.visible = true"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!otherInfo.IsConfirmMedicineQuestion && hasPermi(['trials:trials-panel:setting:medical-audit:confirm'])"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('trials:qcCfg:button:default') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!otherInfo.IsConfirmMedicineQuestion && hasPermi(['trials:trials-panel:setting:medical-audit:confirm'])"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="handleCustomQS"
|
||||
>
|
||||
{{ $t('trials:qcCfg:button:custom') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!otherInfo.IsConfirmMedicineQuestion && hasPermi(['trials:trials-panel:setting:medical-audit:confirm'])"
|
||||
:disabled="otherInfo.QuestionCount===0"
|
||||
type="danger"
|
||||
icon="el-icon-circle-check"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
{{ $t('trials:qcCfg:button:confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
|
||||
v-adaptive="{bottomOffset:45}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
>
|
||||
<!-- <el-table-column type="index" width="60" /> -->
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
:label="$t('trials:qcCfg:table:order')"
|
||||
width="60"
|
||||
/>
|
||||
<!-- 审核问题 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
:label="$t('trials:qcCfg:table:questionName')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 类型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:qcCfg:table:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QcType', scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 选项 -->
|
||||
<el-table-column
|
||||
prop="TypeValue"
|
||||
:label="$t('trials:qcCfg:table:typeValue')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
label="任务类型"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 父问题 -->
|
||||
<el-table-column
|
||||
prop="ParentShowOrder"
|
||||
:label="$t('trials:qcCfg:table:parentQs')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 父问题触发值 -->
|
||||
<el-table-column
|
||||
prop="ParentTriggerValue"
|
||||
:label="$t('trials:qcCfg:table:parentTriggerValue')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:qcCfg:table:isRequired')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 启用状态 -->
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
:label="$t('trials:qcCfg:table:isEnable')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('IsEnable', scope.row.IsEnable) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
v-if="!otherInfo.IsConfirmMedicineQuestion && hasPermi(['trials:trials-panel:setting:medical-audit:confirm'])"
|
||||
:label="$t('common:action:action')"
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('common:button:edit')"
|
||||
icon="el-icon-edit-outline"
|
||||
@click="handleEdit(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('common:button:delete')"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
/>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 新增默认问题 -->
|
||||
<el-dialog
|
||||
v-if="addVisible"
|
||||
:visible.sync="addVisible"
|
||||
width="1100px"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="$t('trials:qcCfg:button:default')"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<DefaultQS @getList="getList" @close="addVisible = false" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 新增/编辑问题 -->
|
||||
<el-dialog
|
||||
v-if="qsForm.visible"
|
||||
:visible.sync="qsForm.visible"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="qsForm.title"
|
||||
width="600px"
|
||||
>
|
||||
<QSForm :data="currentRow" @getList="getList" @close="qsForm.visible = false" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 预览模板 -->
|
||||
<el-dialog
|
||||
v-if="preview.visible"
|
||||
:visible.sync="preview.visible"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="preview.title"
|
||||
width="600px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<QuestionsPreview />
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!--签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span
|
||||
style="font-size:18px;"
|
||||
>
|
||||
{{ $t('common:dialogTitle:sign') }}
|
||||
</span>
|
||||
<span
|
||||
style="font-size:12px;margin-left:5px"
|
||||
>
|
||||
{{ `(${$t('common:label:sign')}${ currentUser })` }}
|
||||
</span>
|
||||
</div>
|
||||
<SignForm
|
||||
ref="signForm"
|
||||
:sign-code-enum="signCode"
|
||||
@closeDialog="closeSignDialog"
|
||||
/>
|
||||
</el-dialog>
|
||||
</box-content>
|
||||
</template>
|
||||
<script>
|
||||
import { getReadingMedicineTrialQuestionList, deleteReadingMedicineTrialQuestion, confirmReadingMedicineQuestion } from '@/api/trials'
|
||||
import BoxContent from '@/components/BoxContent'
|
||||
import DefaultQS from './components/DefaultQS'
|
||||
import QSForm from './components/QSForm'
|
||||
import QuestionsPreview from './components/QuestionsPreview'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import const_ from '@/const/sign-code'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
QuestionName: '',
|
||||
Type: '',
|
||||
IsEnable: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'MedicalAuditQS',
|
||||
components: { BoxContent, DefaultQS, QSForm, QuestionsPreview, SignForm },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
addVisible: false,
|
||||
btnLoading: false,
|
||||
signText: '',
|
||||
signCode: null,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
||||
otherInfo: {
|
||||
IsConfirmMedicineQuestion: true
|
||||
},
|
||||
trialId: '',
|
||||
qsForm: { visible: false, title: '' },
|
||||
preview: { visible: false, title: '预览' },
|
||||
currentRow: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取qc模板信息
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
getReadingMedicineTrialQuestionList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result
|
||||
this.otherInfo = res.OtherInfo
|
||||
this.otherInfo.IsConfirmMedicineQuestion = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
// 打开系统模板配置项
|
||||
handleAdd() {
|
||||
this.addVisible = true
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.qsForm.title = '编辑'
|
||||
this.qsForm.visible = true
|
||||
},
|
||||
// 删除qc问题配置项
|
||||
handleDelete(row) {
|
||||
// 判断该问题是否存在子问题,如果有则不允许删除
|
||||
const i = this.list.findIndex(item => item.ParentId === row.Id)
|
||||
if (i !== -1) {
|
||||
this.$message.error(this.$t('trials:qcCfg:message:deleteWarning'))
|
||||
} else {
|
||||
this.$confirm(this.$t('trials:qcCfg:message:delete'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
trialId: this.trialId,
|
||||
id: row.Id
|
||||
}
|
||||
deleteReadingMedicineTrialQuestion(param)
|
||||
.then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
this.$message.success(this.$t('common:message:deletedSuccessfully'))
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
}
|
||||
},
|
||||
// 打开自定义qc问题配置框
|
||||
handleCustomQS() {
|
||||
this.currentRow = {}
|
||||
this.qsForm.title = '新增'
|
||||
this.qsForm.visible = true
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.getList()
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 确认前签名
|
||||
handleConfirm() {
|
||||
if (this.otherInfo.QuestionCount === 0) {
|
||||
this.$message.error('请先配置医学审核问题再进行确认!')
|
||||
return
|
||||
}
|
||||
const { MedicalAuditConfirmation } = const_.processSignature
|
||||
this.signCode = MedicalAuditConfirmation
|
||||
this.signVisible = true
|
||||
},
|
||||
// 关闭签名框并设置确认状态
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名确认
|
||||
signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
const params = {
|
||||
data: {
|
||||
trialId: this.trialId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
confirmReadingMedicineQuestion(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
this.signVisible = false
|
||||
this.getList()
|
||||
}
|
||||
}).catch(_ => {
|
||||
this.loading = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,899 @@
|
|||
<template>
|
||||
<div
|
||||
id="canvas"
|
||||
ref="canvas"
|
||||
v-loading="loading"
|
||||
element-loading-text="Loading..."
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
style="position:relative;"
|
||||
class="cornerstone-element"
|
||||
>
|
||||
<div v-show="dicomInfo.series" class="info-series">
|
||||
<h2 style="color:#f44336;padding: 5px 0px;margin: 0;">{{ stack.taskBlindName }}</h2>
|
||||
<div>Series #{{ dicomInfo.series }}</div>
|
||||
<div>Image #{{ dicomInfo.frame }}</div>
|
||||
<div>{{ dicomInfo.modality }}</div>
|
||||
</div>
|
||||
<div v-show="dicomInfo.series" class="info-image">
|
||||
<div>
|
||||
P {{ dicomInfo.size }}
|
||||
<span v-show="dicomInfo.pixel">{{ dicomInfo.pixel }}mm</span>
|
||||
</div>
|
||||
<div v-show="dicomInfo.thick">Slice Thickness {{ dicomInfo.thick }}mm</div>
|
||||
<div>WW/WC {{ dicomInfo.wwwc }}</div>
|
||||
<div>Zoom {{ dicomInfo.zoom }}</div>
|
||||
<div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div>
|
||||
<!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
|
||||
</div>
|
||||
|
||||
<div class="info-subject">
|
||||
<!-- <div>{{ dicomInfo.hospital }}</div> -->
|
||||
<div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div>
|
||||
<div>{{ dicomInfo.name }}</div>
|
||||
<!-- <div>{{ dicomInfo.sex }} {{ dicomInfo.age }}</div> -->
|
||||
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
|
||||
<div>{{ dicomInfo.time }}</div>
|
||||
</div>
|
||||
<!-- <div v-show="stack.firstImageLoading" class="load-indicator">
|
||||
Loading Series #{{ stack.seriesNumber }}...
|
||||
</div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Store from './Store'
|
||||
import Vue from 'vue'
|
||||
import Contextmenu from 'vue-contextmenujs'
|
||||
Vue.use(Contextmenu)
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneMath from 'cornerstone-math'
|
||||
import * as cornerstoneTools from 'cornerstone-tools'
|
||||
const scroll = cornerstoneTools.import('util/scrollToIndex')
|
||||
// const drawTextBox = cornerstoneTools.import('drawing/drawTextBox')
|
||||
// const { getNewContext } = cornerstoneTools.import('drawing/index')
|
||||
// const drawLinkedTextBox = cornerstoneTools.import('drawing/drawLinkedTextBox')
|
||||
import Hammer from 'hammerjs'
|
||||
import LengthTool from '@/views/trials/trials-panel/reading/dicoms/tools/Length/LengthTool'
|
||||
import BidirectionalTool from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/BidirectionalTool'
|
||||
import ArrowAnnotateTool from '@/views/trials/trials-panel/reading/dicoms/tools/ArrowAnnotate/ArrowAnnotateTool'
|
||||
cornerstoneTools.external.cornerstone = cornerstone
|
||||
cornerstoneTools.external.Hammer = Hammer
|
||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
||||
cornerstoneTools.toolStyle.setToolWidth(2)
|
||||
cornerstoneTools.toolColors.setToolColor('rgb(255, 255, 0)')
|
||||
cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
|
||||
// cornerstoneTools.init({ globalToolSyncEnabled: true })
|
||||
cornerstoneTools.init()
|
||||
|
||||
export default {
|
||||
name: 'DicomCanvas',
|
||||
props: {
|
||||
isCurrentTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
canvas: {},
|
||||
stack: {
|
||||
studyId: '',
|
||||
seriesId: '',
|
||||
instanceId: '',
|
||||
seriesNumber: '',
|
||||
imageIds: [],
|
||||
currentImageIdIndex: 0,
|
||||
firstImageLoading: false,
|
||||
visitTaskId: '',
|
||||
taskBlindName: ''
|
||||
// preventCache: true
|
||||
},
|
||||
dicomInfo: {
|
||||
hospital: '',
|
||||
pid: '',
|
||||
name: '',
|
||||
sex: '',
|
||||
age: '',
|
||||
acc: '',
|
||||
modality: '',
|
||||
time: '',
|
||||
series: '',
|
||||
frame: '',
|
||||
size: '',
|
||||
pixel: 0,
|
||||
thick: 0,
|
||||
wwwc: '',
|
||||
zoom: 0,
|
||||
fps: 5
|
||||
},
|
||||
toolState: {
|
||||
initialized: false,
|
||||
activeTool: 'none',
|
||||
dicomInfoVisible: false,
|
||||
clipPlaying: false,
|
||||
viewportInvert: false
|
||||
},
|
||||
loadImagePromise: null,
|
||||
AnnotationSync: null,
|
||||
allROIToolData: {},
|
||||
type: '',
|
||||
series: '',
|
||||
ToolStateManager: null,
|
||||
renderedMeasured: [],
|
||||
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate'],
|
||||
measuredData: []
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
||||
this.canvas = this.$refs.canvas
|
||||
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
||||
this.canvas.addEventListener(
|
||||
'cornerstoneimagerendered',
|
||||
this.onImageRendered
|
||||
)
|
||||
this.canvas.addEventListener(
|
||||
'cornerstoneimageloaded',
|
||||
this.onImageLoaded
|
||||
)
|
||||
|
||||
this.canvas.addEventListener(
|
||||
'cornerstonetoolsclipstopped',
|
||||
this.onClipStopped
|
||||
)
|
||||
// this.canvas.addEventListener(
|
||||
// 'cornerstonetoolsmeasurementcompleted',
|
||||
// this.onMeasurementcompleted
|
||||
// )
|
||||
// this.canvas.addEventListener(
|
||||
// 'cornerstonetoolsmeasurementmodified',
|
||||
// this.onMeasurementmodified
|
||||
// )
|
||||
|
||||
// this.canvas.addEventListener(
|
||||
// 'cornerstonetoolsmeasurementremoved',
|
||||
// this.onMeasurementremoved
|
||||
// )
|
||||
this.canvas.addEventListener('cornerstonetoolsmouseup', this.mouseUp)
|
||||
// this.canvas.addEventListener('cornerstonetoolsmouseup', this.mouseDown)
|
||||
this.canvas.addEventListener('cornerstonetoolsmouseclick', this.mouseClick)
|
||||
},
|
||||
|
||||
methods: {
|
||||
mouseDown(e) {
|
||||
return false
|
||||
},
|
||||
mouseUp(e) {
|
||||
console.log('mouseUp')
|
||||
const { element, currentPoints, image } = e.detail
|
||||
var imageId = image.imageId
|
||||
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
this.measuredTools.map(toolType => {
|
||||
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, toolType)
|
||||
if (!toolState) return
|
||||
var toolObj = new cornerstoneTools[`${toolType}Tool`]()
|
||||
var i = toolState.data.findIndex(data => toolObj.pointNearTool(element, data, currentPoints.canvas, 'mouse'))
|
||||
if (i > -1) {
|
||||
const measureData = {}
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
measureData.data = toolState.data[i]
|
||||
measureData.type = toolType
|
||||
measureData.thick = this.dicomInfo.thick
|
||||
var uuid = toolState.data[i].uuid
|
||||
var idx = this.measuredData.findIndex(item => item.MeasureData && item.MeasureData.data.uuid === uuid)
|
||||
if (idx > -1) {
|
||||
var questionInfo = this.measuredData[idx]
|
||||
this.$emit('modifyMeasureData', { measureData, questionInfo })
|
||||
} else {
|
||||
this.$emit('setMeasureData', measureData)
|
||||
}
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
|
||||
}
|
||||
})
|
||||
},
|
||||
mouseClick(e) {
|
||||
const { element, currentPoints } = e.detail
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
this.measuredTools.map(toolType => {
|
||||
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, toolType)
|
||||
if (!toolState) return
|
||||
var toolObj = new cornerstoneTools[`${toolType}Tool`]()
|
||||
// toolState.data.forEach(data => {
|
||||
// // data.color = ''
|
||||
// })
|
||||
var i = toolState.data.findIndex(data => toolObj.pointNearTool(element, data, currentPoints.canvas, 'mouse'))
|
||||
if (i > -1) {
|
||||
// 设置鼠标选中颜色rgb(0, 255, 0)
|
||||
// toolState.data[i].color = ''
|
||||
|
||||
var idx = this.measuredData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
|
||||
if (idx > -1) {
|
||||
Store.$emit('setCollapseActive', this.measuredData[idx])
|
||||
}
|
||||
// toolState.data[i].active = true
|
||||
// cornerstone.updateImage(element)
|
||||
}
|
||||
})
|
||||
},
|
||||
loadImageStack(dicomSeries) {
|
||||
this.series = dicomSeries
|
||||
|
||||
this.stack.seriesId = dicomSeries.seriesId
|
||||
this.stack.studyId = dicomSeries.studyId
|
||||
this.stack.seriesNumber = dicomSeries.seriesNumber
|
||||
this.stack.imageIds = dicomSeries.imageIds
|
||||
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex ? dicomSeries.imageIdIndex : 0
|
||||
this.stack.firstImageLoading = true
|
||||
this.stack.visitTaskId = dicomSeries.visitTaskId
|
||||
this.stack.taskBlindName = dicomSeries.taskBlindName
|
||||
this.measuredData = dicomSeries.measuredData
|
||||
const imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
|
||||
this.stack.instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
|
||||
if (this.toolState.clipPlaying) this.toggleClipPlay()
|
||||
this.toolState.viewportInvert = false
|
||||
this.toolState.dicomInfoVisible = false
|
||||
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
var scope = this
|
||||
// cornerstone.imageCache.setMaximumSizeBytes(100000)
|
||||
// this.loading = true
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
// cornerstone.loadImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
||||
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
||||
.then(image => {
|
||||
// this.loading = false
|
||||
loading.close()
|
||||
scope.onFirstImageLoaded(image)
|
||||
}).catch((error) => {
|
||||
// this.loading = false
|
||||
loading.close()
|
||||
if (error.error && error.error.message) {
|
||||
this.$message.error(error.error.message)
|
||||
}
|
||||
})
|
||||
},
|
||||
onFirstImageLoaded(image) {
|
||||
const element = this.$refs.canvas
|
||||
var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image)
|
||||
cornerstone.displayImage(this.canvas, image, viewport)
|
||||
|
||||
if (!this.toolState.initialized) {
|
||||
this.toolState.initialized = true
|
||||
const toolButtons = document.querySelectorAll('[data-tool]')
|
||||
|
||||
// const scope = this
|
||||
Array.from(toolButtons).forEach((toolBtn) => {
|
||||
// Add the tool
|
||||
const toolName = toolBtn.getAttribute('data-tool')
|
||||
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
||||
|
||||
if (apiTool) {
|
||||
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(
|
||||
element,
|
||||
apiTool
|
||||
)
|
||||
if (!toolAlreadyAddedToElement) {
|
||||
if (toolName === 'Length') {
|
||||
cornerstoneTools.addToolForElement(element, LengthTool)
|
||||
} else if (toolName === 'Bidirectional') {
|
||||
cornerstoneTools.addToolForElement(element, BidirectionalTool)
|
||||
} else if (toolName === 'ArrowAnnotate') {
|
||||
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true }})
|
||||
} else {
|
||||
cornerstoneTools.addToolForElement(element, apiTool)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
if (
|
||||
!cornerstoneTools.getToolForElement(
|
||||
element,
|
||||
cornerstoneTools.StackScrollMouseWheelTool
|
||||
)
|
||||
) {
|
||||
cornerstoneTools.addToolForElement(
|
||||
element,
|
||||
cornerstoneTools.StackScrollMouseWheelTool
|
||||
)
|
||||
}
|
||||
cornerstoneTools.setToolActiveForElement(
|
||||
element,
|
||||
'StackScrollMouseWheel',
|
||||
{}
|
||||
)
|
||||
if (
|
||||
!cornerstoneTools.getToolForElement(
|
||||
element,
|
||||
cornerstoneTools.ScaleOverlayTool
|
||||
)
|
||||
) {
|
||||
cornerstoneTools.addToolForElement(
|
||||
element,
|
||||
cornerstoneTools.ScaleOverlayTool
|
||||
)
|
||||
}
|
||||
cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {})
|
||||
|
||||
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.OrientationMarkersTool)) {
|
||||
cornerstoneTools.addToolForElement(
|
||||
element,
|
||||
cornerstoneTools.OrientationMarkersTool
|
||||
)
|
||||
}
|
||||
cornerstoneTools.setToolActiveForElement(
|
||||
element,
|
||||
'OrientationMarkers',
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
|
||||
cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
|
||||
cornerstoneTools.stackPrefetch.enable(this.canvas)
|
||||
// cornerstoneTools.setElementToolStateManager(this.toolStateManager)
|
||||
cornerstone.updateImage(element, true)
|
||||
// cornerstoneTools.stackPrefetch.setConfiguration({ maxImagesToPrefetch: Infinity,
|
||||
// preserveExistingPool: true })
|
||||
// cornerstoneTools.stackPrefetch.enable(this.canvas)
|
||||
// this.stack.imageIds.forEach((item, index) => {
|
||||
// if (index === 0) {
|
||||
// return
|
||||
// }
|
||||
// cornerstone.loadImage(item)
|
||||
// })
|
||||
|
||||
this.stack.firstImageLoading = false
|
||||
this.toolState.dicomInfoVisible = true
|
||||
|
||||
this.stack.instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
||||
},
|
||||
onNewImage(e) {
|
||||
e.detail.enabledElement.options = {}
|
||||
var data = e.detail.image.data
|
||||
this.dicomInfo.hospital = data.string('x00080080')
|
||||
// this.dicomInfo.pid = data.string('x00100020')
|
||||
this.dicomInfo.pid = data.string('x00120040')
|
||||
this.dicomInfo.name = data.string('x00100010')
|
||||
this.dicomInfo.age = data.string('x00101010')
|
||||
this.dicomInfo.sex = data.string('x00100040')
|
||||
this.dicomInfo.acc = data.string('x00080050') // 登记号
|
||||
this.dicomInfo.modality = data.string('x00080060')
|
||||
this.dicomInfo.time = this.formatDicomDateTime(
|
||||
data.string('x00080020'),
|
||||
data.string('x00080030')
|
||||
)
|
||||
this.dicomInfo.series = data.string('x00200011')
|
||||
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
|
||||
this.stack.imageIds.length
|
||||
}`
|
||||
this.dicomInfo.size = `${data.uint16('x00280010')}x${data.uint16(
|
||||
'x00280011'
|
||||
)}`
|
||||
// var pixel = data.floatString('x00280030')
|
||||
if (this.dicomInfo.pixel) {
|
||||
this.dicomInfo.pixel = this.dicomInfo.pixel.toFixed(2)
|
||||
}
|
||||
this.dicomInfo.thick = data.floatString('x00180050') // 切片厚度
|
||||
if (this.dicomInfo.thick) {
|
||||
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
||||
}
|
||||
},
|
||||
formatDicomDateTime(date, time) {
|
||||
if (date) {
|
||||
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
|
||||
}
|
||||
if (time) { time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}` }
|
||||
return time ? `${date} ${time}` : `${date} 00:00:00`
|
||||
},
|
||||
onImageLoaded(e) {
|
||||
console.log('onImageLoaded')
|
||||
},
|
||||
onImageRendered(e) {
|
||||
console.log('onImageRendered')
|
||||
var imageId = e.detail.image.imageId
|
||||
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||
this.stack.instanceId = instanceId
|
||||
var viewport = e.detail.viewport
|
||||
this.dicomInfo.wwwc = `${Math.round(
|
||||
viewport.voi.windowWidth
|
||||
)}/${Math.round(viewport.voi.windowCenter)}` // 窗位
|
||||
this.dicomInfo.zoom = viewport.scale.toFixed(2)
|
||||
var data = e.detail.image.data
|
||||
const position = data.string('x00200032')
|
||||
this.dicomInfo.location = position ? Number(
|
||||
position.split('\\')[position.split('\\').length - 1]
|
||||
).toFixed(2) : ''
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
this.measuredData.forEach(data => {
|
||||
if (data.SeriesId === this.stack.seriesId && data.InstanceId === this.stack.instanceId && data.MeasureData) {
|
||||
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type)
|
||||
if (toolState && toolState.data.length > 0) {
|
||||
var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid)
|
||||
if (idx === -1) {
|
||||
ToolStateManager.addImageIdToolState(e.detail.image.imageId, data.MeasureData.type, data.MeasureData.data)
|
||||
}
|
||||
} else {
|
||||
ToolStateManager.addImageIdToolState(e.detail.image.imageId, data.MeasureData.type, data.MeasureData.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.measuredTools.forEach(tool => {
|
||||
if (!this.isCurrentTask) {
|
||||
cornerstoneTools.setToolEnabledForElement(this.canvas, tool)
|
||||
} else {
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, tool)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onMeasurementcompleted(e) {
|
||||
// 测量完成
|
||||
console.log('completed')
|
||||
const { image } = e.detail
|
||||
var imageId = image.imageId
|
||||
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||
if (e.detail.toolName === 'Length' || e.detail.toolName === 'Bidirectional' || e.detail.toolName === 'ArrowAnnotate') {
|
||||
const measureData = {}
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
measureData.data = e.detail.measurementData
|
||||
measureData.type = e.detail.toolName
|
||||
measureData.thick = this.dicomInfo.thick
|
||||
this.$emit('setMeasureData', measureData)
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
|
||||
}
|
||||
},
|
||||
onMeasurementremoved(e) {
|
||||
if (e.detail.toolName === 'Length' || e.detail.toolName === 'Bidirectional') {
|
||||
this.$emit('removeMeasureData', e.detail.measurementData.uuid)
|
||||
}
|
||||
},
|
||||
onMeasurementmodified(e) {
|
||||
// 移动
|
||||
console.log('modified')
|
||||
const { image } = e.detail
|
||||
var imageId = image.imageId
|
||||
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
|
||||
|
||||
if (e.detail.toolName === 'Length' || e.detail.toolName === 'Bidirectional' || e.detail.toolName === 'ArrowAnnotate') {
|
||||
const measureData = {}
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
measureData.data = e.detail.measurementData
|
||||
measureData.type = e.detail.toolName
|
||||
measureData.thick = this.dicomInfo.thick
|
||||
var uuid = e.detail.measurementData.uuid
|
||||
var idx = this.measuredData.findIndex(item => item.MeasureData && item.MeasureData.data.uuid === uuid)
|
||||
var questionInfo = idx > -1 ? this.measuredData[idx] : ''
|
||||
this.$emit('modifyMeasureData', { measureData, questionInfo })
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
|
||||
// this.canvas.removeEventListener('mouseup', this.measurementMouseUpHandler)
|
||||
}
|
||||
},
|
||||
measurementMouseUpHandler(e) {
|
||||
console.log('measurementMouseUp')
|
||||
},
|
||||
updateImage(obj) {
|
||||
const element = this.$refs.canvas
|
||||
this.measuredData = obj.measuredData
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
var imageId = `wadouri:/api/instance/content/${obj.instanceId}`
|
||||
ToolStateManager.clearImageIdToolState(imageId)
|
||||
cornerstone.updateImage(element, true)
|
||||
},
|
||||
removeToolState(measuredData) {
|
||||
var idx = this.measuredData.findIndex(item => item.MeasureData && item.MeasureData.data.uuid === measuredData.data.uuid)
|
||||
if (idx > -1) {
|
||||
this.measuredData.splice(idx, 1)
|
||||
const element = this.$refs.canvas
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
var imageId = `wadouri:/api/instance/content/${measuredData.instanceId}`
|
||||
ToolStateManager.clearImageIdToolState(imageId)
|
||||
cornerstone.updateImage(element, true)
|
||||
}
|
||||
},
|
||||
getToolForElement(toolName) {
|
||||
var isExist = false
|
||||
for (var i = 0; i < cornerstoneTools.store.state.tools.length; i++) {
|
||||
if (cornerstoneTools.store.state.tools[i].name === toolName) {
|
||||
isExist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return isExist
|
||||
},
|
||||
onClipStopped() {
|
||||
this.toolState.clipPlaying = false
|
||||
},
|
||||
|
||||
onKeyPress(e) {
|
||||
var key = e.detail.keyCode
|
||||
var keys = { PageUp: 33, PageDown: 34, End: 35, Home: 36 } // Left: 37, Up: 38, Right: 39, Down: 40
|
||||
if (key < keys.PageUp || key > keys.Home) return
|
||||
if (key === keys.Home) this.scrollPage(-9999)
|
||||
else if (key === keys.PageUp) this.scrollPage(-1)
|
||||
else if (key === keys.PageDown) this.scrollPage(1)
|
||||
else if (key === keys.End) this.scrollPage(9999)
|
||||
},
|
||||
|
||||
resizeCanvas() {
|
||||
cornerstone.resize(this.canvas, true)
|
||||
},
|
||||
|
||||
activateCanvas() {
|
||||
this.canvas.tabIndex = 0
|
||||
this.canvas.focus()
|
||||
},
|
||||
|
||||
resetViewport() {
|
||||
this.toolState.viewportInvert = false
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
cornerstone.setViewport(
|
||||
this.canvas,
|
||||
cornerstone.getDefaultViewportForImage(this.canvas, image)
|
||||
)
|
||||
},
|
||||
|
||||
toggleDicomInfo() {
|
||||
this.toolState.dicomInfoVisible = !this.toolState.dicomInfoVisible
|
||||
if (this.toolState.dicomInfoVisible) {
|
||||
cornerstoneTools.orientationMarkers.enable(this.canvas)
|
||||
} else cornerstoneTools.orientationMarkers.disable(this.canvas)
|
||||
cornerstone.updateImage(this.canvas)
|
||||
},
|
||||
setColormap(colormap) {
|
||||
const viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.colormap = colormap
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
cornerstone.updateImage(this.canvas, true)
|
||||
if (!colormap) {
|
||||
this.resetRenderCanvase(this.canvas)
|
||||
}
|
||||
},
|
||||
resetRenderCanvase(element) {
|
||||
const enabledElement = cornerstone.getEnabledElement(element)
|
||||
|
||||
enabledElement.renderingTools.colormapId = undefined
|
||||
enabledElement.renderingTools.colorLut = undefined
|
||||
|
||||
const renderCanvas = enabledElement.renderingTools.renderCanvas
|
||||
const canvasContext = renderCanvas.getContext('2d')
|
||||
canvasContext.fillStyle = 'white'
|
||||
canvasContext.fillRect(0, 0, renderCanvas.width, renderCanvas.height)
|
||||
|
||||
const renderCanvasData = canvasContext.getImageData(
|
||||
0,
|
||||
0,
|
||||
renderCanvas.width,
|
||||
renderCanvas.height
|
||||
)
|
||||
|
||||
enabledElement.renderingTools.renderCanvasContext = canvasContext
|
||||
enabledElement.renderingTools.renderCanvasData = renderCanvasData
|
||||
},
|
||||
scrollPage(offset) {
|
||||
var index = this.stack.currentImageIdIndex + offset
|
||||
if (index < 0) index = 0
|
||||
else if (index >= this.stack.imageIds.length) {
|
||||
index = this.stack.imageIds.length - 1
|
||||
}
|
||||
if (index !== this.stack.currentImageIdIndex) {
|
||||
scroll(this.canvas, index)
|
||||
}
|
||||
},
|
||||
|
||||
toggleClipPlay() {
|
||||
if (this.toolState.clipPlaying) {
|
||||
cornerstoneTools.stopClip(this.canvas)
|
||||
this.toolState.clipPlaying = false
|
||||
return
|
||||
}
|
||||
this.toolState.clipPlaying = true
|
||||
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
||||
cornerstoneTools.getToolState(
|
||||
this.canvas,
|
||||
'playClip'
|
||||
).data[0].loop = false
|
||||
},
|
||||
setFps(fps) {
|
||||
this.dicomInfo.fps = fps
|
||||
},
|
||||
|
||||
resetWwwc() {
|
||||
this.toolState.viewportInvert = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.invert = false
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
viewport.voi.windowWidth = image.windowWidth
|
||||
viewport.voi.windowCenter = image.windowCenter
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
},
|
||||
|
||||
setWwwc(ww, wc) {
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.voi.windowWidth = ww
|
||||
viewport.voi.windowCenter = wc
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
},
|
||||
|
||||
toggleInvert() {
|
||||
this.toolState.viewportInvert = !this.toolState.viewportInvert
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.invert = this.toolState.viewportInvert
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
},
|
||||
|
||||
activateZoom() {
|
||||
cornerstoneTools.addTool(cornerstoneTools.ZoomTool, {
|
||||
configuration: {
|
||||
invert: false,
|
||||
preventZoomOutsideImage: false,
|
||||
minScale: 0.1,
|
||||
maxScale: 20.0
|
||||
}
|
||||
})
|
||||
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
||||
this.toolState.activeTool = 'zoom'
|
||||
},
|
||||
|
||||
resetRotate() {
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.hflip = false
|
||||
viewport.vflip = false
|
||||
viewport.rotation = 0
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
},
|
||||
|
||||
setRotate(hflip, vflip, angle) {
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
if (hflip) viewport.hflip = !viewport.hflip
|
||||
if (vflip) viewport.vflip = !viewport.vflip
|
||||
if (angle !== 0) viewport.rotation += angle
|
||||
cornerstone.setViewport(this.canvas, viewport)
|
||||
},
|
||||
|
||||
saveImage() {
|
||||
var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
|
||||
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
|
||||
},
|
||||
fitToWindow() {
|
||||
if (this.stack.seriesNumber) {
|
||||
cornerstone.fitToWindow(this.canvas)
|
||||
}
|
||||
},
|
||||
fitToImage() {
|
||||
if (this.stack.seriesNumber) {
|
||||
const enabledElement = cornerstone.getEnabledElement(this.canvas)
|
||||
enabledElement.viewport.scale = 1
|
||||
cornerstone.updateImage(this.canvas)
|
||||
}
|
||||
},
|
||||
|
||||
removeLabel(item) {
|
||||
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
||||
const scope = this
|
||||
Promise.all([promise]).then(res => {
|
||||
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
||||
cornerstone.updateImage(scope.canvas)
|
||||
})
|
||||
},
|
||||
setToolPassive(toolName) {
|
||||
// 它们的数据可以被操作,但不能创建。
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
||||
},
|
||||
setToolActive(toolName) {
|
||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||
mouseButtonMask: 1
|
||||
})
|
||||
},
|
||||
setToolEnabled(toolName) {
|
||||
// 工具将呈现,但不会对输入作出反应
|
||||
cornerstoneTools.setToolEnabledForElement(this.canvas, toolName)
|
||||
},
|
||||
setAllToolsPassive() {
|
||||
cornerstoneTools.store.state.tools.forEach((tool) => {
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, tool.name)
|
||||
})
|
||||
},
|
||||
|
||||
addTargetElement(synchronizer) {
|
||||
synchronizer.addTarget(this.$refs.canvas)
|
||||
},
|
||||
removeTarget(synchronizer) {
|
||||
synchronizer.removeTarget(this.$refs.canvas)
|
||||
},
|
||||
addSourceElement(synchronizer) {
|
||||
synchronizer.addSource(this.$refs.canvas)
|
||||
},
|
||||
removeSource(synchronizer) {
|
||||
synchronizer.removeSource(this.$refs.canvas)
|
||||
},
|
||||
activeReferenceLine(synchronizer) {
|
||||
if (
|
||||
!cornerstoneTools.getToolForElement(
|
||||
this.canvas,
|
||||
cornerstoneTools.ReferenceLinesTool
|
||||
)
|
||||
) {
|
||||
cornerstoneTools.addToolForElement(
|
||||
this.canvas,
|
||||
cornerstoneTools.ReferenceLinesTool
|
||||
)
|
||||
}
|
||||
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
||||
synchronizationContext: synchronizer
|
||||
})
|
||||
|
||||
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
||||
// cornerstoneTools.setToolActive('Crosshairs', {
|
||||
// mouseButtonMask: 1,
|
||||
// synchronizationContext: synchronizer
|
||||
// })
|
||||
},
|
||||
disabledReferenceLine(synchronizer) {
|
||||
synchronizer.enabled = false
|
||||
synchronizer.remove(this.canvas)
|
||||
cornerstoneTools.setToolDisabledForElement(this.canvas, 'ReferenceLines')
|
||||
// cornerstoneTools.setToolDisabledForElement(this.canvas, 'Crosshairs')
|
||||
},
|
||||
activeViewPortToolSync(synchronizer, toolName) {
|
||||
synchronizer.add(this.canvas)
|
||||
synchronizer.enabled = true
|
||||
if (
|
||||
!cornerstoneTools.getToolForElement(
|
||||
this.canvas,
|
||||
cornerstoneTools[`${toolName}Tool`]
|
||||
)
|
||||
) {
|
||||
cornerstoneTools.addToolForElement(
|
||||
this.canvas,
|
||||
cornerstoneTools[`${toolName}Tool`]
|
||||
)
|
||||
}
|
||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||
mouseButtonMask: 1,
|
||||
synchronizationContext: synchronizer
|
||||
})
|
||||
},
|
||||
disabledViewPortToolSync(synchronizer, toolName) {
|
||||
synchronizer.enabled = false
|
||||
synchronizer.remove(this.canvas)
|
||||
cornerstoneTools.setToolDisabledForElement(this.canvas, toolName)
|
||||
},
|
||||
activeImageSync(synchronizer) {
|
||||
synchronizer.add(this.$refs.canvas)
|
||||
synchronizer.enabled = true
|
||||
return false
|
||||
},
|
||||
disabledImageSync(synchronizer) {
|
||||
synchronizer.remove(this.$refs.canvas)
|
||||
synchronizer.enabled = false
|
||||
return false
|
||||
},
|
||||
activeAnnotationSync(synchronizer) {
|
||||
this.AnnotationSync = synchronizer
|
||||
synchronizer.add(this.$refs.canvas)
|
||||
synchronizer.enabled = true
|
||||
},
|
||||
disabledAnnotationSync(synchronizer) {
|
||||
this.AnnotationSync = null
|
||||
synchronizer.enabled = false
|
||||
synchronizer.remove(this.$refs.canvas)
|
||||
this.setAllToolsPassive()
|
||||
},
|
||||
getToolSate() {
|
||||
const toolROITypes = [
|
||||
'Probe',
|
||||
'EllipticalRoi',
|
||||
'RectangleRoi',
|
||||
'ArrowAnnotate',
|
||||
'Length',
|
||||
'CobbAngle',
|
||||
'Angle',
|
||||
'Bidirectional',
|
||||
'FreehandRoi'
|
||||
]
|
||||
for (let i = 0; i < toolROITypes.length; i++) {
|
||||
const toolROIType = toolROITypes[i]
|
||||
const toolROIData = JSON.stringify(
|
||||
cornerstoneTools.getToolState(this.canvas, toolROIType)
|
||||
)
|
||||
|
||||
if (toolROIData !== undefined) {
|
||||
this.allROIToolData[toolROITypes[i]] = JSON.parse(toolROIData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.info-series {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
text-align: left;
|
||||
color: #ddd;
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
.info-image {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
bottom: 10px;
|
||||
text-align: left;
|
||||
color: #ddd;
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.info-subject {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
text-align: right;
|
||||
color: #ddd;
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.load-indicator {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
text-align: left;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.magnifyTool {
|
||||
border: 2px solid #ffffff;
|
||||
border-radius: 50%;
|
||||
display: none;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
.menu__item {
|
||||
display: block;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
cursor: default;
|
||||
}
|
||||
.menu__item:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.menu {
|
||||
height: auto;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #c21111;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
li:hover {
|
||||
background-color: #e0e0e2;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,953 @@
|
|||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<h3 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ taskBlindName }}
|
||||
</h3>
|
||||
<!-- 非测量问题 -->
|
||||
<div class="lesions">
|
||||
<Questions ref="ecrf" />
|
||||
</div>
|
||||
<!-- 测量问题 -->
|
||||
<template v-if="questions.length > 0 && CriterionType !== 10">
|
||||
<div v-for="(qs,index) in questions" :key="index" v-loading="loading" class="lesions lesions_wrapper">
|
||||
<h4 v-if="qs.Type === 'group'" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ qs.GroupName }}
|
||||
</h4>
|
||||
<div class="lesion_list">
|
||||
<div v-for="item in qs.Childrens" v-show="!(isBaseLineTask && item.LesionType === 2)" :key="item.Id">
|
||||
<div v-if="item.Type === 'table'" class="flex-row">
|
||||
<div class="title">{{ item.QuestionName }}</div>
|
||||
<div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- @change="handleCollapseChange(qs.Childrens,item)" -->
|
||||
<el-collapse
|
||||
v-if="item.Type === 'table' && item.TableQuestions"
|
||||
v-model="activeName"
|
||||
accordion
|
||||
@change="handleCollapseChange"
|
||||
>
|
||||
<el-collapse-item
|
||||
v-for="(q,i) in item.TableQuestions.Answers"
|
||||
:key="i"
|
||||
:name="`${item.Id}_${q.RowIndex}`"
|
||||
>
|
||||
<template slot="title">
|
||||
<div style="width:300px;position: relative;" :style="{color:(activeName===item.Id+q.RowIndex?'#ffeb3b':'#fff')}">
|
||||
<el-tooltip v-show="readingTaskState<2 && !!item.TableQuestions.Answers[i].RowId && !isBaseLineTask && item.TableQuestions.Answers[i].isDicomReading !== false" class="item" content="分裂" placement="left">
|
||||
<i class="el-icon-plus" style="color:#fff;font-size: 16px;" @click.stop="handleSplit(item.TableQuestions.Answers[i].RowId,item.Id)" />
|
||||
</el-tooltip>
|
||||
{{ getLesionName(item.OrderMark,q.RowIndex) }}
|
||||
<el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) === 0" class="item" effect="dark" content="未保存" placement="bottom">
|
||||
<i class="el-icon-warning" style="color:red" />
|
||||
</el-tooltip>
|
||||
<el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) ===1" class="item" effect="dark" content="信息不完整" placement="bottom">
|
||||
<i class="el-icon-warning" style="color:#ff9800" />
|
||||
</el-tooltip>
|
||||
<div style="position: absolute;left: 60px;top: 2px;">
|
||||
<div style="display: flex;flex-direction: row;font-size: 10px;width:200px;">
|
||||
<div v-if="item.TableQuestions.Answers[i].lesionPart" style="margin-left:10px;margin-bottom:5px;">
|
||||
{{ item.TableQuestions.Answers[i].lesionPart }}
|
||||
</div>
|
||||
<div v-if="item.TableQuestions.Answers[i].lesionState" style="margin-left:10px;margin-bottom:5px;">
|
||||
<span v-if="item.LesionType === 0">
|
||||
{{ $fd('TargetState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
|
||||
</span>
|
||||
<span v-else-if="item.LesionType === 1">
|
||||
{{ $fd('NoTargetState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $fd('NewLesionState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
|
||||
</span>
|
||||
</div>
|
||||
<div style="margin-left:10px;margin-bottom:5px;">
|
||||
<template v-if="item.TableQuestions.Answers[i].isLymphLesion && item.TableQuestions.Answers[i].lesionShort">
|
||||
{{ item.TableQuestions.Answers[i].lesionShort }}mm
|
||||
</template>
|
||||
<template v-else-if="!item.TableQuestions.Answers[i].isLymphLesion && item.TableQuestions.Answers[i].lesionLength">
|
||||
{{ item.TableQuestions.Answers[i].lesionLength }}mm
|
||||
</template>
|
||||
<!-- <span v-if="item.TableQuestions.Answers[i].lesionLength && item.TableQuestions.Answers[i].lesionShort">
|
||||
{{ item.TableQuestions.Answers[i].lesionShort }}mm
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ item.TableQuestions.Answers[i].lesionLength? `${item.TableQuestions.Answers[i].lesionLength}mm`:'' }}
|
||||
</span> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<MeasurementForm
|
||||
:ref="`${item.Id}_${q.RowIndex}`"
|
||||
:questions="item.TableQuestions.Questions"
|
||||
:answers="item.TableQuestions.Answers[i]"
|
||||
:lesion-type="item.LesionType"
|
||||
:order-mark="item.OrderMark"
|
||||
:table-questions="tableQuestions"
|
||||
:row-index="String(q.RowIndex)"
|
||||
:question-name="item.QuestionName"
|
||||
:parent-qs-id="item.Id"
|
||||
:visit-task-id="visitTaskId"
|
||||
:is-current-task="isCurrentTask"
|
||||
:reading-task-state="readingTaskState"
|
||||
:is-base-line-task="isBaseLineTask"
|
||||
@getReadingQuestionAndAnswer="getReadingQuestionAndAnswer"
|
||||
@determineExistsUnsavedLession="determineExistsUnsavedLession"
|
||||
@resetQuestions="resetQuestions"
|
||||
@close="close"
|
||||
/>
|
||||
</el-collapse-item>
|
||||
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="questions.length > 0 && CriterionType === 10">
|
||||
<PCWG3Questions ref="pcwg3" :questions="questions" :reading-task-state-parent="readingTaskState" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { splitLesion } from '@/api/trials'
|
||||
import DicomEvent from './DicomEvent'
|
||||
import PCWG3Questions from './questions/PCWG3Questions'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import Questions from './Questions'
|
||||
import MeasurementForm from './MeasurementForm'
|
||||
export default {
|
||||
name: 'MeasurementList',
|
||||
components: {
|
||||
Questions,
|
||||
MeasurementForm,
|
||||
PCWG3Questions
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
activeRowIndex: null,
|
||||
activeCollapseId: null
|
||||
},
|
||||
visitTaskId: '',
|
||||
isCurrentTask: false,
|
||||
loading: false,
|
||||
unSaveTargets: [],
|
||||
temporaryLesions: [],
|
||||
readingTaskState: 2,
|
||||
isBaseLineTask: false,
|
||||
taskBlindName: '',
|
||||
tableQuestions: [],
|
||||
isFirstRender: false,
|
||||
CriterionType: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList'])
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('message', this.receiveMsg)
|
||||
this.CriterionType = parseInt(this.$route.query.CriterionType)
|
||||
DicomEvent.$on('loadMeasurementList', async obj => {
|
||||
if (this.visitTaskId !== obj.visitTaskId) {
|
||||
this.visitTaskId = obj.visitTaskId
|
||||
this.taskBlindName = obj.taskBlindName
|
||||
this.activeName = ''
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
}
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.getQuestions(this.visitTaskList[idx].ReadingQuestions)
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
this.getTableQuestions()
|
||||
if (this.isFirstRender) {
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!this.isFirstRender) {
|
||||
this.isFirstRender = true
|
||||
}
|
||||
console.log('loadMeasurementList')
|
||||
})
|
||||
DicomEvent.$on('setCollapseActive', measureData => {
|
||||
this.setCollapseActive(measureData)
|
||||
console.log('setCollapseActive')
|
||||
})
|
||||
DicomEvent.$on('changeLesionType', (questionsObj) => {
|
||||
this.changeLesionType(questionsObj)
|
||||
console.log('changeLesionType')
|
||||
})
|
||||
DicomEvent.$on('getAllUnSaveLesions', (callback) => {
|
||||
var list = this.getAllUnSaveLesions()
|
||||
callback(list)
|
||||
console.log('getAllUnSaveLesions')
|
||||
})
|
||||
|
||||
DicomEvent.$on('split', measureData => {
|
||||
this.handleSplit(measureData.RowId, measureData.QuestionId)
|
||||
})
|
||||
DicomEvent.$on('setReadingState', readingTaskState => {
|
||||
this.readingTaskState = readingTaskState
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('loadMeasurementList')
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
DicomEvent.$off('changeLesionType')
|
||||
DicomEvent.$off('getUnSaveTarget')
|
||||
DicomEvent.$off('setReadingState')
|
||||
},
|
||||
methods: {
|
||||
|
||||
initPage(obj) {
|
||||
if (this.visitTaskId !== obj.visitTaskId) {
|
||||
this.visitTaskId = obj.visitTaskId
|
||||
this.taskBlindName = obj.taskBlindName
|
||||
this.activeName = ''
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
}
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
this.getTableQuestions()
|
||||
if (this.isFirstRender) {
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!this.isFirstRender) {
|
||||
this.isFirstRender = true
|
||||
}
|
||||
if (this.CriterionType === 10) {
|
||||
this.$nextTick(() => {
|
||||
console.log(this.$refs)
|
||||
console.log(this.$refs.pcwg3)
|
||||
console.log(this.$refs.pcwg3.initPage(obj))
|
||||
})
|
||||
}
|
||||
},
|
||||
async resetQuestions(obj) {
|
||||
this.setQuestions(this.questions, obj)
|
||||
console.log(this.questions)
|
||||
await store.dispatch('reading/setReadingQuestionAndAnswer', { questions: this.questions, visitTaskId: this.visitTaskId })
|
||||
|
||||
this.getTableQuestions()
|
||||
},
|
||||
setQuestions(questions, obj) {
|
||||
questions.forEach(item => {
|
||||
if (item.Type === 'table' && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion
|
||||
item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan
|
||||
item.TableQuestions.Answers[idx].lesionPart = obj.lesionPart
|
||||
item.TableQuestions.Answers[idx].lesionLength = obj.lesionLength
|
||||
item.TableQuestions.Answers[idx].lesionShort = obj.lesionShort
|
||||
item.TableQuestions.Answers[idx].lesionState = obj.lesionState
|
||||
|
||||
item.TableQuestions.Answers[idx].saveTypeEnum = obj.saveTypeEnum
|
||||
|
||||
for (const i in obj.anwsers) {
|
||||
if (i === 'MeasureData' && obj.anwsers[i]) {
|
||||
item.TableQuestions.Answers[idx].InstanceId = obj.anwsers[i].instanceId
|
||||
item.TableQuestions.Answers[idx].SeriesId = obj.anwsers[i].seriesId
|
||||
item.TableQuestions.Answers[idx][i] = JSON.stringify(obj.anwsers[i])
|
||||
item.TableQuestions.Answers[idx].isDicomReading = !(obj.anwsers[i].IsDicomReading === false || obj.anwsers[i].IsDicomReading === 'False')
|
||||
} else {
|
||||
item.TableQuestions.Answers[idx][i] = String(obj.anwsers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestions(item.Childrens, obj)
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestions(questions) {
|
||||
questions.forEach(item => {
|
||||
if (item.Type === 'table' && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
this.$set(answerObj, 'loctation', this.getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj))
|
||||
this.$set(answerObj, 'lesionLength', this.getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj))
|
||||
this.$set(answerObj, 'lesionShort', this.getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj))
|
||||
var isLymphLesion = this.getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
|
||||
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
|
||||
this.$set(answerObj, 'isLymphLesion', isLymphLesion)
|
||||
|
||||
var lesionState = this.getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
|
||||
lesionState = lesionState ? parseInt(lesionState) : ''
|
||||
this.$set(answerObj, 'lesionState', lesionState)
|
||||
|
||||
if (answerObj.RowId) {
|
||||
this.$set(answerObj, 'saveTypeEnum', isNaN(parseInt(lesionState)) ? 1 : 2)
|
||||
} else {
|
||||
this.$set(answerObj, 'saveTypeEnum', 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getQuestions(item.Childrens)
|
||||
}
|
||||
})
|
||||
return questions
|
||||
},
|
||||
getTableQuestions() {
|
||||
this.tableQuestions = []
|
||||
this.questions.map(item => {
|
||||
if (item.Type === 'table') {
|
||||
this.tableQuestions.push(item)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getTableQuestionsChild(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
getTableQuestionsChild(obj) {
|
||||
obj.map(item => {
|
||||
if (item.Type === 'table') {
|
||||
this.tableQuestions.push(item)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getTableQuestionsChild(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
refreshReadingQuestionAndAnswer(type) {
|
||||
if (type === 0) {
|
||||
// 删除
|
||||
this.activeName = ''
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
}
|
||||
|
||||
this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
},
|
||||
getReadingQuestionAndAnswer() {
|
||||
return new Promise(async resolve => {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
await store.dispatch('reading/refreshReadingQuestionAndAnswer', { trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId }).then(() => {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
}
|
||||
this.getTableQuestions()
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
await store.dispatch('reading/refreshMeasuredData', this.visitTaskId)
|
||||
DicomEvent.$emit('getMeasureData')
|
||||
loading.close()
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
var questionId = questions[idx].Id
|
||||
return answers[questionId]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 分裂
|
||||
handleSplit(rowId, questionId) {
|
||||
var arr = []
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
this.unSaveTargets.forEach(item => {
|
||||
arr.push(item.lessionName)
|
||||
})
|
||||
}
|
||||
var unSavedList = this.getAllUnSaveLesions()
|
||||
unSavedList.forEach(item => {
|
||||
arr.push(item.lessionName)
|
||||
})
|
||||
if (arr.length > 0) {
|
||||
var message = arr.join('、')
|
||||
this.$confirm(`病灶${message},未保存。如果分裂,信息将被还原,是否继续?`, {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.split(rowId, questionId)
|
||||
})
|
||||
.catch(() => {})
|
||||
} else {
|
||||
this.$confirm('是否确认分裂?', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.split(rowId, questionId)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
},
|
||||
split(rowId, questionId) {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
questionId: questionId,
|
||||
rowId: rowId
|
||||
}
|
||||
splitLesion(params).then(async res => {
|
||||
loading.close()
|
||||
await this.getReadingQuestionAndAnswer()
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
isCanActiveTool(toolName) {
|
||||
if (this.CriterionType === 10) {
|
||||
return this.$refs['pcwg3'].isCanActiveTool(toolName)
|
||||
} else {
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
var rowIndex = String(this.unSaveTargets[0].rowIndex)
|
||||
var questionId = this.unSaveTargets[0].questionId
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (rowIndex === this.activeItem.activeRowIndex && questionId === this.activeItem.activeCollapseId && !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
return this.checkToolCanActive(toolName)
|
||||
} else {
|
||||
return { isCanActiveTool: false, reason: `病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许继续添加!` }
|
||||
}
|
||||
} else {
|
||||
if (this.activeItem.activeCollapseId) {
|
||||
return this.checkToolCanActive(toolName)
|
||||
} else {
|
||||
if (toolName === 'ArrowAnnotate' || toolName === 'Bidirectional' || toolName === 'Length') {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
} else {
|
||||
return { isCanActiveTool: false, reason: '' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
checkToolCanActive(toolName) {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
var isLymphNodes = this.$refs[refName][0].getQuestionVal(2)
|
||||
isLymphNodes = !isNaN(parseInt(isLymphNodes)) ? parseInt(isLymphNodes) : null
|
||||
if (!this.$refs[refName][0].questionForm.MeasureData) {
|
||||
if (this.isBaseLineTask) {
|
||||
if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 1 && toolName !== 'Bidirectional') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结靶病灶需使用长短径测量工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 0 && toolName !== 'Length') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结靶病灶需使用直径测量工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结非靶病灶需使用长短径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结非靶病灶需使用直径测量工具或箭头工具' }
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
} else {
|
||||
if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结靶病灶需使用长短径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结非靶病灶需使用直径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结非靶病灶需使用长短径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结非靶病灶需使用直径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 2 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结新病灶需使用长短径测量工具或箭头工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 2 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结新病灶需使用直径测量工具或箭头工具' }
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
},
|
||||
|
||||
async handleAdd(qs) {
|
||||
// 判断是否有未保存的病灶
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
this.$confirm(`病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许继续添加!`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!!qs.MaxQuestionCount && qs.MaxQuestionCount <= qs.TableQuestions.Answers.length) {
|
||||
this.$confirm(`${qs.QuestionName}个数最多不能超过${qs.MaxQuestionCount}个`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
} else {
|
||||
// saveTypeEnum: 0
|
||||
var obj = { saveTypeEnum: 0 }
|
||||
var questions = qs.TableQuestions.Questions.find(item => item.QuestionMark === 3)
|
||||
if (questions) {
|
||||
var maxIndex = this.getMaxRowIndex(qs.TableQuestions.Answers)
|
||||
obj.RowIndex = `${maxIndex + 1}.00`
|
||||
obj[questions.Id] = `${qs.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
|
||||
}
|
||||
obj.IsDicomReading = true
|
||||
await store.dispatch('reading/addReadingQuestionAndAnswer', { lesionType: qs.LesionType, visitTaskId: this.visitTaskId, lesionObj: obj })
|
||||
|
||||
this.activeItem.activeRowIndex = String(obj.RowIndex)
|
||||
this.activeItem.activeCollapseId = qs.Id
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
}
|
||||
},
|
||||
getMaxRowIndex(answerList) {
|
||||
if (answerList.length > 0) {
|
||||
var arr = []
|
||||
answerList.forEach(item => {
|
||||
var rowIndex = item.RowIndex
|
||||
arr.push(parseInt(rowIndex))
|
||||
})
|
||||
var max = Math.max.apply(null, arr)
|
||||
return max
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
determineExistsUnsavedLession(callback) {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
var rowIndex = String(this.unSaveTargets[0].rowIndex)
|
||||
var questionId = this.unSaveTargets[0].questionId
|
||||
if (rowIndex === String(this.activeItem.activeRowIndex) && questionId === this.activeItem.activeCollapseId) {
|
||||
callback(true)
|
||||
// loading.close()
|
||||
return
|
||||
} else {
|
||||
this.$confirm(`病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许执行此操作!`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => { }
|
||||
})
|
||||
callback(false)
|
||||
// loading.close()
|
||||
return
|
||||
}
|
||||
}
|
||||
callback(true)
|
||||
// loading.close()
|
||||
return
|
||||
},
|
||||
getUnSaveTarget() {
|
||||
this.unSaveTargets = []
|
||||
this.tableQuestions.map(item => {
|
||||
if (item.TableQuestions && item.TableQuestions.Answers) {
|
||||
item.TableQuestions.Answers.map(t => {
|
||||
if (!t.RowId) {
|
||||
var lessionName = this.getLesionName(item.OrderMark, t.RowIndex)
|
||||
this.unSaveTargets.push({ lessionName: lessionName, rowIndex: t.RowIndex, questionId: item.Id })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
// console.log(this.unSaveTargets)
|
||||
return this.unSaveTargets
|
||||
},
|
||||
getAllUnSaveLesions() {
|
||||
var arr = []
|
||||
this.tableQuestions.map(item => {
|
||||
if (item.TableQuestions && item.TableQuestions.Answers) {
|
||||
item.TableQuestions.Answers.map(t => {
|
||||
const refName = `${item.Id}_${t.RowIndex}`
|
||||
if (this.$refs[refName] && this.$refs[refName][0] && this.$refs[refName][0].questionForm.saveTypeEnum !== 2) {
|
||||
var lessionName = this.getLesionName(item.OrderMark, t.RowIndex)
|
||||
arr.push({ lessionName: lessionName, rowIndex: t.RowIndex, questionId: item.Id })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return arr
|
||||
},
|
||||
getLesionName(orderMark, rowIndex) {
|
||||
var lessionName = ''
|
||||
var rowIndexArr = rowIndex.split('.')
|
||||
var x = parseInt(rowIndexArr[0])
|
||||
var y = parseInt(rowIndexArr[1])
|
||||
if (y > 0) {
|
||||
y = String.fromCharCode(parseInt(rowIndexArr[1]) - 1 + 65 + 32)
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}${y}`
|
||||
} else {
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
return lessionName
|
||||
},
|
||||
handleCollapseChange(val) {
|
||||
if (this.activeName) {
|
||||
var arr = this.activeName.split('_')
|
||||
this.activeItem.activeRowIndex = arr[1]
|
||||
this.activeItem.activeCollapseId = arr[0]
|
||||
this.$nextTick(() => {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (this.$refs[refName][0].questionForm.IsDicomReading !== false) {
|
||||
DicomEvent.$emit('imageLocation', { questionId: this.activeItem.activeCollapseId, rowIndex: this.activeItem.activeRowIndex, visitTaskId: this.visitTaskId })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
}
|
||||
},
|
||||
// 更改病灶类型
|
||||
async changeLesionType(questionsObj) {
|
||||
await store.dispatch('reading/removeReadingQuestionAndAnswer', { lesionType: questionsObj.oldLesionType, rowIndex: questionsObj.rowIndex, visitTaskId: this.visitTaskId })
|
||||
// saveTypeEnum: 0
|
||||
var lesionObj = { }
|
||||
var questionObj = questionsObj.questionForm
|
||||
// 切换到新的病灶集合
|
||||
var targetObj = this.tableQuestions.find(item => item.LesionType === questionsObj.newLesionType)
|
||||
var lesionMark = ''
|
||||
targetObj.TableQuestions.Questions.forEach(i => {
|
||||
if (i.QuestionMark === 3) {
|
||||
var maxIndex = this.getMaxRowIndex(targetObj.TableQuestions.Answers)
|
||||
lesionObj.RowIndex = `${maxIndex + 1}.00`
|
||||
lesionObj[i.Id] = `${targetObj.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
|
||||
lesionMark = lesionObj[i.Id]
|
||||
} else {
|
||||
var obj = questionObj.find(v => v.QuestionMark === i.QuestionMark)
|
||||
if (obj) {
|
||||
lesionObj[i.Id] = obj.Answer
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (questionsObj.measureData) {
|
||||
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: questionsObj.measureData, questionId: questionsObj.questionId, rowIndex: questionsObj.rowIndex })
|
||||
questionsObj.measureData.data.remark = lesionMark
|
||||
lesionObj.MeasureData = JSON.stringify(questionsObj.measureData)
|
||||
}
|
||||
|
||||
await store.dispatch('reading/addReadingQuestionAndAnswer', { lesionType: questionsObj.newLesionType, visitTaskId: this.visitTaskId, lesionObj: lesionObj })
|
||||
|
||||
this.activeItem.activeRowIndex = String(lesionObj.RowIndex)
|
||||
this.activeItem.activeCollapseId = targetObj.Id
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
this.$nextTick(() => {
|
||||
this.$refs[refName][0].setMeasureData(questionsObj.measureData)
|
||||
})
|
||||
},
|
||||
removeQuestionAnswer(questionsObj) {
|
||||
// 移除当前病灶
|
||||
var currentObj = this.tableQuestions.find(item => item.LesionType === questionsObj.oldLesionType)
|
||||
if (currentObj) {
|
||||
var i = currentObj.TableQuestions.Answers.findIndex(i => String(i.RowIndex) === String(questionsObj.rowIndex))
|
||||
if (i === -1) return
|
||||
currentObj.TableQuestions.Answers.splice(i, 1)
|
||||
}
|
||||
},
|
||||
// 创建新病灶
|
||||
createNLTarget(measureData) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 2)
|
||||
if (idx > -1) {
|
||||
this.addTarget(this.tableQuestions[idx], measureData)
|
||||
}
|
||||
},
|
||||
// 创建靶病灶
|
||||
createTTarget(measureData) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 0)
|
||||
if (idx > -1) {
|
||||
this.addTarget(this.tableQuestions[idx], measureData)
|
||||
}
|
||||
},
|
||||
|
||||
async addTarget(target, measureData) {
|
||||
// saveTypeEnum: 0
|
||||
var obj = {}
|
||||
|
||||
// obj.RowIndex = target.TableQuestions.Answers.length + 1
|
||||
var questions = target.TableQuestions.Questions.find(item => item.QuestionMark === 3)
|
||||
if (questions) {
|
||||
var maxIndex = this.getMaxRowIndex(target.TableQuestions.Answers)
|
||||
obj.RowIndex = `${maxIndex + 1}.00`
|
||||
obj[questions.Id] = `${target.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
|
||||
// obj[questions.Id] = `${target.OrderMark}${String(obj.RowIndex).padStart(2, '0')}`
|
||||
}
|
||||
// target.TableQuestions.Answers.push(obj)
|
||||
obj.IsDicomReading = !(measureData.isDicomReading === false || measureData.isDicomReading === 'False')
|
||||
obj.measureObj = measureData
|
||||
await store.dispatch('reading/addReadingQuestionAndAnswer', { lesionType: target.LesionType, visitTaskId: this.visitTaskId, lesionObj: obj })
|
||||
|
||||
this.activeItem.activeRowIndex = String(obj.RowIndex)
|
||||
this.activeItem.activeCollapseId = target.Id
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
// const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs[refName][0].setMeasureData(measureData)
|
||||
// })
|
||||
},
|
||||
createNTTarget(measureData) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 1)
|
||||
if (idx > -1) {
|
||||
this.addTarget(this.tableQuestions[idx], measureData)
|
||||
}
|
||||
},
|
||||
setCollapseActive(measureData) {
|
||||
if (measureData) {
|
||||
if (this.activeItem.activeRowIndex === measureData.RowIndex && this.activeItem.activeCollapseId === measureData.QuestionId) {
|
||||
return
|
||||
} else {
|
||||
this.activeItem.activeCollapseId = measureData.QuestionId
|
||||
this.activeItem.activeRowIndex = measureData.RowIndex
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
}
|
||||
}
|
||||
},
|
||||
modifyMeasuredData(measureObj) {
|
||||
if (this.CriterionType !== 10) {
|
||||
if (measureObj.questionInfo) {
|
||||
this.activeItem.activeCollapseId = measureObj.questionInfo.QuestionId
|
||||
this.activeItem.activeRowIndex = String(measureObj.questionInfo.RowIndex)
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
this.$refs[refName][0].setMeasureData(measureObj.measureData)
|
||||
}
|
||||
} else {
|
||||
this.$refs['pcwg3'].modifyMeasuredData(measureObj)
|
||||
}
|
||||
},
|
||||
// 设置测量数据
|
||||
setMeasuredData(measureData) {
|
||||
if (this.CriterionType !== 10) {
|
||||
if (this.activeItem.activeCollapseId) {
|
||||
// 判断是否存在测量数据
|
||||
this.$nextTick(() => {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if ((this.$refs[refName][0].questionForm && this.$refs[refName][0].questionForm.MeasureData && measureData.data.uuid === this.$refs[refName][0].questionForm.MeasureData.data.uuid) || !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
this.$refs[refName][0].setMeasureData(measureData)
|
||||
} else {
|
||||
if (this.isBaseLineTask) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 0)
|
||||
if (this.tableQuestions[idx].TableQuestions.Answers.length < this.tableQuestions[idx].MaxQuestionCount && (measureData.type === 'Length' || measureData.type === 'Bidirectional')) {
|
||||
this.createTTarget(measureData)
|
||||
} else {
|
||||
this.createNTTarget(measureData)
|
||||
}
|
||||
} else {
|
||||
this.createNLTarget(measureData)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (this.isBaseLineTask) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 0)
|
||||
if (this.tableQuestions[idx].TableQuestions.Answers.length < this.tableQuestions[idx].MaxQuestionCount && (measureData.type === 'Length' || measureData.type === 'Bidirectional')) {
|
||||
this.createTTarget(measureData)
|
||||
} else {
|
||||
this.createNTTarget(measureData)
|
||||
}
|
||||
} else {
|
||||
this.createNLTarget(measureData)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.$refs['pcwg3'].setMeasuredData(measureData)
|
||||
}
|
||||
},
|
||||
async close(questionsObj) {
|
||||
if (questionsObj) {
|
||||
this.getReadingQuestionAndAnswer(questionsObj.visitTaskId)
|
||||
}
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
this.activeName = ''
|
||||
},
|
||||
getECRFQuestions(obj) {
|
||||
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
},
|
||||
receiveMsg(event) {
|
||||
if (event.data.type === 'isCanActiveNoneDicomTool') {
|
||||
this.getUnSaveTarget()
|
||||
var obj = {}
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
var rowIndex = String(this.unSaveTargets[0].rowIndex)
|
||||
var questionId = this.unSaveTargets[0].questionId
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (rowIndex === this.activeItem.activeRowIndex && questionId === this.activeItem.activeCollapseId && !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
// 判断是否是靶病灶
|
||||
// questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
var lesionType = this.$refs[refName][0].questionForm.LesionType
|
||||
if (lesionType === 0) {
|
||||
obj = { isCanActiveTool: false, lesionName: '', reason: '当前病灶为靶病灶,不允许添加标记!' }
|
||||
} else {
|
||||
obj = { isCanActiveTool: true, lesionName: this.$refs[refName][0].lesionMark, reason: '' }
|
||||
}
|
||||
} else {
|
||||
obj = { isCanActiveTool: false, lesionName: '', reason: `病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许添加!` }
|
||||
}
|
||||
} else {
|
||||
if (this.activeItem.activeCollapseId) {
|
||||
// 判断是否是靶病灶
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
obj = { isCanActiveTool: true, lesionName: this.$refs[refName][0].lesionMark, reason: '' }
|
||||
} else {
|
||||
// 获取非靶病灶/新病灶的长度及标识
|
||||
var qsObj = null
|
||||
var lesionName = ''
|
||||
if (this.isBaseLineTask) {
|
||||
const idx = this.tableQuestions.findIndex(item => item.LesionType === 1)
|
||||
if (idx > -1) {
|
||||
qsObj = this.tableQuestions[idx]
|
||||
}
|
||||
} else {
|
||||
const idx = this.tableQuestions.findIndex(item => item.LesionType === 2)
|
||||
if (idx > -1) {
|
||||
qsObj = this.tableQuestions[idx]
|
||||
}
|
||||
}
|
||||
|
||||
var questions = qsObj.TableQuestions.Questions.find(item => item.QuestionMark === 3)
|
||||
if (questions) {
|
||||
var maxIndex = this.getMaxRowIndex(qsObj.TableQuestions.Answers)
|
||||
lesionName = `${qsObj.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
|
||||
}
|
||||
obj = { isCanActiveTool: true, lesionName: lesionName, reason: '' }
|
||||
}
|
||||
}
|
||||
|
||||
DicomEvent.$emit('isCanActiveNoneDicomTool', obj)
|
||||
} else if (event.data.type === 'setMeasurement') {
|
||||
this.setMeasuredData(event.data.data)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
.container{
|
||||
padding: 10px;
|
||||
}
|
||||
.title{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
.add-icon{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
border: 1px solid #938b8b;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #424242;
|
||||
|
||||
}
|
||||
.lesion_list{
|
||||
position: relative;
|
||||
}
|
||||
.el-collapse{
|
||||
border-bottom:none;
|
||||
>>>.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
>>>.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
padding-left: 5px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
>>>.el-collapse-item__wrap{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
}
|
||||
>>>.el-collapse-item__content{
|
||||
width:260px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
border: 1px solid #ffeb3b;
|
||||
z-index: 1;
|
||||
color: #ddd;
|
||||
padding: 5px;
|
||||
background-color:#1e1e1e;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<QuestionsPreview v-if="trialCriterionId" :criterion-id="trialCriterionId" :is-system-criterion="isSystemCriterion" :form-type="1" style="padding:10px;" />
|
||||
</template>
|
||||
<script>
|
||||
import QuestionsPreview from './components/QuestionsPreview'
|
||||
export default {
|
||||
name: 'CriterionQuestions',
|
||||
components: { QuestionsPreview },
|
||||
data() {
|
||||
return {
|
||||
trialCriterionId: '',
|
||||
isSystemCriterion: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.$route.query)
|
||||
this.trialCriterionId = this.$route.query.TrialReadingCriterionId
|
||||
this.isSystemCriterion = this.$route.query.isSystemCriterion === 'true'
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,548 @@
|
|||
<template>
|
||||
<div class="dicom-viewer-wrapper">
|
||||
<div class="dicom-viewer-container">
|
||||
<div class="dicom-tools">
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div class="dropdown">
|
||||
<div class="icon">
|
||||
<svg-icon icon-class="layout" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">布局<i class="el-icon-caret-bottom" /></div>
|
||||
<div class="dropdown-content">
|
||||
<ul style="width:40px">
|
||||
<li v-for="layout in layouts" :key="layout.index">
|
||||
<a href="#" @click.prevent="changeLayout(layout)">{{ layout.row }}*{{ layout.col }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='Zoom'?'tool_active':'']"
|
||||
data-tool="Zoom"
|
||||
@click.prevent="setToolActive('Zoom',false)"
|
||||
>
|
||||
<svg-icon icon-class="magnifier" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">缩放</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='Pan'?'tool_active':'']"
|
||||
data-tool="Pan"
|
||||
@click.prevent="setToolActive('Pan',false)"
|
||||
>
|
||||
<svg-icon icon-class="move" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">移动</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
@click.prevent="fitToType('fitToWindow')"
|
||||
>
|
||||
<svg-icon icon-class="fitToWindow" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">适应窗口</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
@click.prevent="fitToType('fitToImage')"
|
||||
>
|
||||
<svg-icon icon-class="fitToImage" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">适应图像</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='Length'?'tool_active':'']"
|
||||
data-tool="Length"
|
||||
@click.prevent="setToolActive('Length',true)"
|
||||
>
|
||||
<svg-icon icon-class="length" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">长度测量</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='Bidirectional'?'tool_active':'']"
|
||||
data-tool="Bidirectional"
|
||||
@click.prevent="setToolActive('Bidirectional',true)"
|
||||
>
|
||||
<svg-icon icon-class="bidirection" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">十字线</div>
|
||||
</div>
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='ArrowAnnotate'?'tool_active':'']"
|
||||
data-tool="ArrowAnnotate"
|
||||
@click.prevent="setToolActive('ArrowAnnotate',true)"
|
||||
>
|
||||
<svg-icon icon-class="label" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">文字标注</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="tool-wrapper">
|
||||
<div
|
||||
class="icon"
|
||||
:class="[activeTool==='Eraser'?'tool_active':'']"
|
||||
data-tool="Eraser"
|
||||
@click.prevent="setToolActive('Eraser')"
|
||||
>
|
||||
<svg-icon icon-class="clear" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">清除标记</div>
|
||||
</div> -->
|
||||
|
||||
<div class="tool-wrapper">
|
||||
<div class="dropdown">
|
||||
<div class="icon">
|
||||
<svg-icon icon-class="more" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">更多<i class="el-icon-caret-bottom" /></div>
|
||||
<div class="dropdown-content">
|
||||
<ul style="width:90px;text-align: left;">
|
||||
<li>
|
||||
<a href="#">
|
||||
<svg-icon icon-class="angle" />
|
||||
角度测量
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<svg-icon icon-class="cobb" />
|
||||
Cobb测量
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<svg-icon icon-class="oval" />
|
||||
椭圆测量
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<svg-icon icon-class="rectangle" />
|
||||
矩形测量
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
<svg-icon icon-class="image" />
|
||||
导出Png图像
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="dicom-viewers">
|
||||
<div ref="container" class="viewer-container" :class="['box', `box_${layoutRow}_${layoutCol}`]">
|
||||
<div
|
||||
v-for="i in maxCanvas"
|
||||
:key="i"
|
||||
:class="['item', i-1===currentDicomCanvasIndex?'item_active':'']"
|
||||
:data-index="i-1"
|
||||
@click="activateDicomCanvas(i-1)"
|
||||
>
|
||||
<dicom-canvas
|
||||
v-if="canvasW"
|
||||
:ref="`dicomCanvas${i-1}`"
|
||||
:style="{width:canvasW,height: canvasH}"
|
||||
:is-current-task="isCurrentTask"
|
||||
:is-active="i-1===currentDicomCanvasIndex"
|
||||
@setMeasureData="setMeasureData"
|
||||
@removeMeasureData="removeMeasureData"
|
||||
@modifyMeasureData="modifyMeasureData"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="form-container" class="form-container">
|
||||
|
||||
<MeasurementList
|
||||
v-if="visitTaskId"
|
||||
ref="measurementList"
|
||||
:is-current-task="isCurrentTask"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneMath from 'cornerstone-math'
|
||||
import * as cornerstoneTools from 'cornerstone-tools'
|
||||
import Hammer from 'hammerjs'
|
||||
cornerstoneTools.external.cornerstone = cornerstone
|
||||
cornerstoneTools.external.Hammer = Hammer
|
||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
||||
import DicomCanvas from './DicomCanvas'
|
||||
import MeasurementList from './MeasurementList'
|
||||
import Store from './Store'
|
||||
export default {
|
||||
name: 'DicomViewer',
|
||||
components: { DicomCanvas, MeasurementList },
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isCurrentTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
layouts: [
|
||||
{ index: 0, row: 1, col: 1 },
|
||||
{ index: 1, row: 1, col: 2 },
|
||||
{ index: 2, row: 2, col: 1 },
|
||||
{ index: 3, row: 2, col: 2 }
|
||||
],
|
||||
maxCanvas: 1,
|
||||
layoutRow: 1,
|
||||
layoutCol: 1,
|
||||
currentDicomCanvasIndex: 0,
|
||||
currentDicomCanvas: {
|
||||
toolState: {
|
||||
clipPlaying: false
|
||||
}
|
||||
},
|
||||
colormapsList: [],
|
||||
rotateList: [],
|
||||
colorList: [],
|
||||
wwwcList: [],
|
||||
canvasW: null,
|
||||
canvasH: null,
|
||||
activeTool: '',
|
||||
measuredTools: ['Length', 'Bidirectional']
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.rotateList[0] = '1'
|
||||
this.colorList[0] = ''
|
||||
this.wwwcList[0] = '1'
|
||||
this.colormapsList = cornerstone.colors.getColormapsList()
|
||||
this.currentDicomCanvas = this.$refs['dicomCanvas0'] ? this.$refs['dicomCanvas0'][0] : ''
|
||||
this.setCanvasStyle()
|
||||
window.addEventListener('resize', this.setCanvasStyle)
|
||||
Store.$on('updateImage', (measureData) => {
|
||||
for (let i = 0; i < this.maxCanvas; i++) {
|
||||
var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
|
||||
if (stack.studyId) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].updateImage(measureData)
|
||||
}
|
||||
}
|
||||
console.log('updateImage')
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
Store.$off('updateImage')
|
||||
},
|
||||
methods: {
|
||||
loadImageStack(dicomSeries) {
|
||||
if (this.activeTool) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
|
||||
this.activeTool = ''
|
||||
}
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].loadImageStack(dicomSeries)
|
||||
},
|
||||
|
||||
// 设置画布大小
|
||||
setCanvasStyle() {
|
||||
this.canvasW = (window.innerWidth - 520) / this.layoutCol + 'px'
|
||||
this.canvasH = (window.innerHeight - 130) / this.layoutRow + 'px'
|
||||
},
|
||||
// 切换布局
|
||||
changeLayout(layout) {
|
||||
this.layoutRow = layout.row
|
||||
this.layoutCol = layout.col
|
||||
this.setCanvasStyle()
|
||||
this.maxCanvas = layout.row * layout.col
|
||||
this.$nextTick(() => {
|
||||
const elements = document.querySelectorAll('.cornerstone-element')
|
||||
Array.from(elements).forEach((element) => {
|
||||
cornerstone.enable(element)
|
||||
cornerstone.resize(element)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 激活画布
|
||||
activateDicomCanvas(index) {
|
||||
if (index !== this.currentDicomCanvasIndex) {
|
||||
if (this.activeTool) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
|
||||
this.activeTool = ''
|
||||
}
|
||||
|
||||
this.currentDicomCanvasIndex = index
|
||||
this.currentDicomCanvas = this.$refs[`dicomCanvas${index}`]
|
||||
this.currentDicomCanvas.tabIndex = 0
|
||||
if (!this.rotateList[this.currentDicomCanvasIndex]) {
|
||||
this.rotateList[this.currentDicomCanvasIndex] = '1'
|
||||
}
|
||||
if (!this.colorList[this.currentDicomCanvasIndex]) {
|
||||
this.colorList[this.currentDicomCanvasIndex] = ''
|
||||
}
|
||||
if (!this.wwwcList[this.currentDicomCanvasIndex]) {
|
||||
this.wwwcList[this.currentDicomCanvasIndex] = '1'
|
||||
}
|
||||
var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
|
||||
if (stack.studyId) {
|
||||
Store.$emit('toggleVisitList', stack)
|
||||
}
|
||||
}
|
||||
},
|
||||
setToolActive(toolName, isMeasuredTool) {
|
||||
console.log((!this.isCurrentTask && isMeasuredTool) || this.readingTaskState >= 2)
|
||||
if ((!this.isCurrentTask && isMeasuredTool) || this.readingTaskState >= 2) {
|
||||
this.activeTool = ''
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
|
||||
return
|
||||
}
|
||||
if (this.activeTool === toolName) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
|
||||
this.activeTool = ''
|
||||
} else {
|
||||
if (this.measuredTools.includes(toolName)) {
|
||||
var isCanActiveTool = this.$refs['measurementList'].isCanActiveTool()
|
||||
if (isCanActiveTool) {
|
||||
this.activeTool = toolName
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive(toolName)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setToolEnabled() {
|
||||
if (!this.isCurrentTask) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
|
||||
this.activeTool = ''
|
||||
return
|
||||
}
|
||||
if (this.activeTool) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
|
||||
this.activeTool = ''
|
||||
}
|
||||
},
|
||||
fitToType(toolName) {
|
||||
if (this.activeTool !== 'fitToWindow' && this.activeTool !== 'fitToImage') {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
|
||||
}
|
||||
if (toolName === 'fitToWindow') {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToWindow()
|
||||
} else if (toolName === 'fitToImage') {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToImage()
|
||||
}
|
||||
this.activeTool = toolName
|
||||
},
|
||||
setMeasureData(data) {
|
||||
this.$refs['measurementList'].setMeasuredData(data)
|
||||
this.activeTool = ''
|
||||
},
|
||||
removeMeasureData(uuid) {
|
||||
console.log(uuid)
|
||||
},
|
||||
modifyMeasureData(data) {
|
||||
this.$refs['measurementList'].modifyMeasuredData(data)
|
||||
this.activeTool = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.dicom-viewer-wrapper{
|
||||
height: 100%;
|
||||
padding: 5px 0px 5px 5px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.dicom-viewer-container{
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.dicom-tools{
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #727272;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
.tool-wrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
.icon{
|
||||
padding: 5px;
|
||||
border: 1px solid #404040;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
.svg-icon{
|
||||
font-size:20px;
|
||||
color:#ddd;
|
||||
}
|
||||
}
|
||||
.text{
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
color: #d0d0d0;
|
||||
}
|
||||
}
|
||||
.tool_active{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
.icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
.text{
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #383838;
|
||||
color: #fff;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
ul{
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
li{
|
||||
a{
|
||||
display: block;
|
||||
padding: 5px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul li:hover a{
|
||||
background-color: #727272;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.dicom-viewers{
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
// width: 100%;
|
||||
margin-top: 5px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
.viewer-container{
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border: 1px solid #727272;
|
||||
}
|
||||
.form-container{
|
||||
// box-sizing: border-box;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
border: 1px solid #727272;
|
||||
// overflow-y: auto;
|
||||
}
|
||||
.measurement-container{
|
||||
// height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.box{
|
||||
display: grid;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
.item{
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
border: 1px solid rgba(255, 255, 255, 0.21);
|
||||
position: relative;
|
||||
&_active{
|
||||
border: 1px solid #5297b9;
|
||||
}
|
||||
}
|
||||
}
|
||||
.box_1_1{
|
||||
grid-template-columns: repeat(1, 100%); //1列,占100%
|
||||
grid-template-rows: repeat(1, 100%); //1行,占100%
|
||||
}
|
||||
.box_1_2{
|
||||
grid-template-columns: repeat(2, 50%); //1列,占50%
|
||||
grid-template-rows: repeat(1, 100%); //1行,占100%
|
||||
}
|
||||
.box_2_1{
|
||||
grid-template-columns: repeat(1, 100%); //1列,占100%
|
||||
grid-template-rows: repeat(2, 50%); //1行,占50%
|
||||
}
|
||||
.box_2_2{
|
||||
grid-template-columns: repeat(2, 50%); //1列,占50%
|
||||
grid-template-rows: repeat(2, 50%); //1行,占50%
|
||||
}
|
||||
|
||||
// .box_3_1{
|
||||
// grid-template-columns: repeat(3, 100%); //1列,占100%
|
||||
// grid-template-rows: repeat(3, 33.33%); //1行,占100%
|
||||
// }
|
||||
// .box_3_2{
|
||||
// grid-template-columns: repeat(3, 50%); //1列,占100%
|
||||
// grid-template-rows: repeat(3, 50%); //1行,占100%
|
||||
// }
|
||||
// .box_3_3{
|
||||
// grid-template-columns: repeat(3, 33.33%); //1列,占100%
|
||||
// grid-template-rows: repeat(3, 33.33%); //1行,占100%
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,221 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="taskAllocationRuleDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
size="small"
|
||||
>
|
||||
<div v-if="list.length > 0">
|
||||
<div style="text-align: right">
|
||||
<el-button size="mini" type="primary" style="position:relative;top: -10px" @click="clearAll">
|
||||
<!-- 清空全部未读阅片人 -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:clearAll')}}
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-if="readingType === 1" style="line-height: 32px;margin-bottom: 10px;">
|
||||
<!-- 阅片人(R1): -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:r1')}}
|
||||
<el-tag v-if="findDoctorUser(list, 0).DoctorUser && !findDoctorUser(list, 0).IsCancelAssign" :closable="!findDoctorUser(list, 0).IsHaveReading" @close="myClose(findDoctorUser(list, 0))">
|
||||
{{findDoctorUser(list, 0).DoctorUser.UserName}}({{findDoctorUser(list, 0).DoctorUser.FullName}})
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="readingType === 2" style="line-height: 32px;margin-bottom: 10px;">
|
||||
<!-- 阅片人(R1): -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:r1')}}
|
||||
<el-tag v-if="findDoctorUser(list, 1).DoctorUser && !findDoctorUser(list, 1).IsCancelAssign" :closable="!findDoctorUser(list, 1).IsHaveReading" @close="myClose(findDoctorUser(list, 1))">
|
||||
{{findDoctorUser(list, 1).DoctorUser.UserName}}({{findDoctorUser(list, 1).DoctorUser.FullName}})
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="readingType === 2" style="line-height: 32px;margin-bottom: 10px;">
|
||||
<!-- 阅片人(R2): -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:r2')}}
|
||||
<el-tag v-if="findDoctorUser(list, 2).DoctorUser && !findDoctorUser(list, 2).IsCancelAssign" :closable="!findDoctorUser(list, 2).IsHaveReading" @close="myClose(findDoctorUser(list, 2))">
|
||||
{{findDoctorUser(list, 2).DoctorUser.UserName}}({{findDoctorUser(list, 2).DoctorUser.FullName}})
|
||||
</el-tag>
|
||||
</div>
|
||||
<div v-if="OtherInfo && OtherInfo.IsArbitrationReading && readingType === 2" style="line-height: 32px;margin-bottom: 10px;">
|
||||
<!-- 裁判(AD): -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:ad')}}
|
||||
<el-tag v-if="findDoctorUser(list, 3).DoctorUser && !findDoctorUser(list, 3).IsCancelAssign" :closable="!findDoctorUser(list, 3).IsHaveReading" @close="myClose(findDoctorUser(list, 3))">
|
||||
{{findDoctorUser(list, 3).DoctorUser.UserName}}({{findDoctorUser(list, 3).DoctorUser.FullName}})
|
||||
</el-tag>
|
||||
</div>
|
||||
<div style="line-height: 32px;margin-bottom: 10px;" v-if="OtherInfo && OtherInfo.IsOncologyReading">
|
||||
<!-- 肿瘤阅片人(O1): -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:O1')}}
|
||||
<el-tag v-if="findDoctorUser(list, 4).DoctorUser && !findDoctorUser(list, 4).IsCancelAssign" :closable="!findDoctorUser(list, 4).IsHaveReading" @close="myClose(findDoctorUser(list, 4))">
|
||||
{{findDoctorUser(list, 4).DoctorUser.UserName}}({{findDoctorUser(list, 4).DoctorUser.FullName}})
|
||||
</el-tag>
|
||||
</div>
|
||||
<div style="line-height: 32px;margin-bottom: 10px;font-size: 12px;color:#f66;">
|
||||
<i class="el-icon-info"></i>
|
||||
<!-- 如果分配的阅片人已开始读片则不能清空 -->
|
||||
{{$t('trials:reviewAssign:clearReader:title:msg1')}}
|
||||
</div>
|
||||
<div>
|
||||
<!-- 原因 -->
|
||||
<el-form-item label-width="80px" :label="$t('trials:reviewAssign:clearReader:title:reason')" prop="Note">
|
||||
<el-input v-model="form.Note" type="textarea" maxlength="500" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 保存 -->
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="loading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" :loading="loading" style="margin-top: 10px;" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSubjectAssignedDoctorList, cancelSubjectAssignedDoctor, addSubjectCancelDoctorNote } from '@/api/trials/reading'
|
||||
|
||||
export default {
|
||||
name: 'ManualAllocationTable',
|
||||
props: {
|
||||
TrialReadingCriterionId: {
|
||||
type: String,
|
||||
default() {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingType: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
TrialId: this.$route.query.trialId,
|
||||
list: [],
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
form: {
|
||||
Note: ''
|
||||
},
|
||||
readingType: null,
|
||||
rules: {
|
||||
Note: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
},
|
||||
OtherInfo: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getSubjectAssignedDoctorList(this.data.SubjectId, this.TrialReadingCriterionId).then(res => {
|
||||
this.list = res.Result
|
||||
this.readingType = res.OtherInfo.ReadingType
|
||||
this.OtherInfo = Object.assign({}, res.OtherInfo)
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
clearAll () {
|
||||
var is = false
|
||||
this.form.Note = ''
|
||||
this.list.forEach((v,i) => {
|
||||
if (!v.IsHaveReading) {
|
||||
this.$set(v, 'IsCancelAssign', true)
|
||||
if (i + 1 === this.list.length) {
|
||||
// this.form.Note += `取消${this.$fd('ArmEnum', v.ArmEnum)}阅片人${v.DoctorUser.UserName}(${v.DoctorUser.FullName});`
|
||||
trials:reviewAssign:clearReader:title:cancelReader
|
||||
this.form.Note += `${this.$t('trials:reviewAssign:clearReader:title:cancelReader')}(${this.$fd('ArmEnum', v.ArmEnum)} ${v.DoctorUser.UserName}(${v.DoctorUser.FullName});`
|
||||
} else {
|
||||
// this.form.Note += `取消${this.$fd('ArmEnum', v.ArmEnum)}阅片人${v.DoctorUser.UserName}(${v.DoctorUser.FullName});\n`
|
||||
this.form.Note += `${this.$t('trials:reviewAssign:clearReader:title:cancelReader')}(${this.$fd('ArmEnum', v.ArmEnum)} ${v.DoctorUser.UserName}(${v.DoctorUser.FullName});\n`
|
||||
}
|
||||
is = true
|
||||
}
|
||||
})
|
||||
if (is) {
|
||||
// '已全部清空,请点击保存应用'
|
||||
this.$message.success(this.$t('trials:reviewAssign:clearReader:title:msg2'))
|
||||
} else {
|
||||
// '没有可清空的阅片人'
|
||||
this.$message.error(this.$t('trials:reviewAssign:clearReader:title:msg3'))
|
||||
}
|
||||
},
|
||||
myClose(o) {
|
||||
this.$set(o, 'IsCancelAssign', true)
|
||||
if (this.form.Note) {
|
||||
// this.form.Note += `\n取消${this.$fd('ArmEnum', o.ArmEnum)}阅片人${o.DoctorUser.UserName}(${o.DoctorUser.FullName});`
|
||||
this.form.Note += `\n${this.$t('trials:reviewAssign:clearReader:title:cancelReader')}(${this.$fd('ArmEnum', o.ArmEnum)} ${o.DoctorUser.UserName}(${o.DoctorUser.FullName});`
|
||||
} else {
|
||||
// this.form.Note += `取消${this.$fd('ArmEnum', o.ArmEnum)}阅片人${o.DoctorUser.UserName}(${o.DoctorUser.FullName});`
|
||||
this.form.Note += `${this.$t('trials:reviewAssign:clearReader:title:cancelReader')}(${this.$fd('ArmEnum', o.ArmEnum)} ${o.DoctorUser.UserName}(${o.DoctorUser.FullName});`
|
||||
}
|
||||
},
|
||||
findDoctorUser(list, type) {
|
||||
var a
|
||||
if (list.length > 0) {
|
||||
a = list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) ? list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) : {
|
||||
DoctorUser: null
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
save() {
|
||||
this.$refs.taskAllocationRuleDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
var params = this.list.map(v => {
|
||||
return {
|
||||
Id: v.Id,
|
||||
SubjectId: this.data.SubjectId,
|
||||
DoctorUserId: v.DoctorUserId,
|
||||
ArmEnum: v.ArmEnum,
|
||||
IsCancelAssign: v.IsCancelAssign
|
||||
}
|
||||
})
|
||||
cancelSubjectAssignedDoctor({
|
||||
CancelList: params,
|
||||
Note: this.form.Note,
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId,
|
||||
TrialId: this.TrialId
|
||||
}).then(() => {
|
||||
this.loading = false
|
||||
// '保存成功'
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.$emit('getList')
|
||||
this.close()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
close() { this.$emit('close') }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,684 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="clinicalDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
:disabled="type === 'look'"
|
||||
label-width="130px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="类型" prop="ClinicalQuestionType">
|
||||
<el-select v-model="form.ClinicalQuestionType" clearable @change="((val)=>{typeChange(val, form)})">
|
||||
<el-option
|
||||
v-for="item of $d.ClinicalQuestionType"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="问题名称"
|
||||
prop="QuestionName"
|
||||
>
|
||||
<el-input v-model="form.QuestionName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="问题名称(EN)"
|
||||
prop="QuestionEnName"
|
||||
>
|
||||
<el-input v-model="form.QuestionEnName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType === 'select' || form.ClinicalQuestionType === 'radio' || form.ClinicalQuestionType === 'checkbox'"
|
||||
label="选项"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.TypeValue"
|
||||
placeholder="选项请用‘|’分割多个选项"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType === 'number'"
|
||||
label="小数位数"
|
||||
prop="DigitPlaces"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.DigitPlaces"
|
||||
style="line-height: 40px;"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.DigitPlaces"
|
||||
:key="`DigitPlaces${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType === 'number'"
|
||||
label="单位"
|
||||
prop="Unit"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.Unit"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div v-if="form.ClinicalQuestionType === 'number'" style="background: #f8f8f8;padding: 10px 0px;border-radius: 10px;position: relative;margin-bottom: 10px;">
|
||||
<!-- 运算类型 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:customCalculateMark')"
|
||||
prop="CustomCalculateMark"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.CustomCalculateMark"
|
||||
style="line-height: 40px;"
|
||||
@change="(v) => CustomCalculateMarkChange(v)"
|
||||
>
|
||||
<div>
|
||||
<el-radio
|
||||
v-for="item of $d.ClinicalCustomCalculateMark"
|
||||
v-show="item.value <= 4"
|
||||
:key="`CustomCalculateMark${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</div>
|
||||
<div>
|
||||
<el-radio
|
||||
v-for="item of $d.ClinicalCustomCalculateMark"
|
||||
v-show="item.value > 4"
|
||||
:key="`CustomCalculateMark${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</div>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-table
|
||||
v-if="isShow"
|
||||
ref="CalculateTable"
|
||||
:data="form.CalculateQuestions"
|
||||
style="margin: 10px;width: calc(100% - 20px)"
|
||||
size="small"
|
||||
>
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:qsList:title:order')"
|
||||
min-width="70"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 运算类型 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:qsList:title:customCalculateMark')"
|
||||
show-overflow-tooltip
|
||||
min-width="70"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('ClinicalCustomCalculateMark', form.CustomCalculateMark) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 问题名称 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:qsList:title:qsName')"
|
||||
prop="TableQuestionId"
|
||||
show-overflow-tooltip
|
||||
min-width="180"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.TableQuestionId" clearable>
|
||||
<el-option v-for="item of Questions" :key="item.QuestionId" :label="item.QuestionName" :value="item.QuestionId" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="form.CustomCalculateMark <= 4"
|
||||
:label="$t('common:action:action')"
|
||||
prop="TableQuestionId"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 添加 -->
|
||||
<el-button
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
circle
|
||||
:title="$t('trials:readingUnit:qsList:title:add')"
|
||||
@click="addCustomCalculateMark(scope.$index)"
|
||||
/>
|
||||
<!-- 删除 -->
|
||||
<el-button
|
||||
icon="el-icon-minus"
|
||||
size="mini"
|
||||
circle
|
||||
:disabled="form.CalculateQuestions.length <= 2"
|
||||
:title="$t('trials:readingUnit:qsList:title:delete')"
|
||||
@click="deleteCustomCalculateMark(scope.$index)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="font-size: 12px;color:#666;padding: 0 15px 0;text-align: right" v-if="form.CustomCalculateMark !== -1">
|
||||
<!-- '请选择同级问题!': '请选择表格问题下的子问题!' -->
|
||||
<i class="el-icon-info" />{{ [1, 2, 3, 4, 9, -1].includes(form.CustomCalculateMark) ? $t('trials:readingUnit:qsList:message:msg1') : $t('trials:readingUnit:qsList:message:msg2') }}
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group'" label="是否显示" prop="ClinicalQuestionShowEnum">
|
||||
<el-radio-group
|
||||
v-model="form.ClinicalQuestionShowEnum"
|
||||
@change="((val)=>{isShowQuestionChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ClinicalQuestionShow"
|
||||
:key="`ClinicalQuestionShowEnum${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType !== 'group' && form.ClinicalQuestionShowEnum===1"
|
||||
label="显示依赖父问题"
|
||||
prop="ParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`ParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.Id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 显示时依赖父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId && form.ClinicalQuestionShowEnum===1" label="显示触发值" prop="ParentTriggerValue">
|
||||
<el-select v-model="form.ParentTriggerValue" clearable>
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value.toString()"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group' && form.ClinicalQuestionType !== 'table'" :label="$t('trials:readingUnit:qsList:title:isRequired')" prop="IsRequired">
|
||||
<el-radio-group
|
||||
v-model="form.IsRequired"
|
||||
:disabled="form.IsJudgeQuestion===true || form.ShowQuestion===2"
|
||||
@change="((val)=>{isRequiredChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.QuestionRequired"
|
||||
:key="`QuestionRequired${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.ClinicalQuestionType !== 'group' && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceId')"
|
||||
prop="RelevanceId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.RelevanceId"
|
||||
clearable
|
||||
@change="((val)=>{relevanceQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`RelevanceId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.Id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 必填触发值 -->
|
||||
<el-form-item
|
||||
v-if="form.RelevanceId && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceValueList')"
|
||||
prop="RelevanceValue"
|
||||
>
|
||||
<el-select v-model="form.RelevanceValue" clearable>
|
||||
<el-option
|
||||
v-for="item of reParentTriggerValOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'group'" prop="GroupId" label="问题分组">
|
||||
<el-select v-model="form.GroupId" clearable :disabled="isParentExistGroup">
|
||||
<el-option
|
||||
v-for="group of groupOptions"
|
||||
:key="group.Id"
|
||||
:label="group.QuestionName"
|
||||
:value="group.Id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType === 'time' && [2, 3].includes(clinicalInfo.ClinicalDataLevel)" label="是否为检查日期" prop="IsCheckDate">
|
||||
<el-radio-group
|
||||
v-model="form.IsCheckDate"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsCheckDate${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType !== 'table' && form.ClinicalQuestionType !== 'group' && form.ClinicalQuestionType !== 'number'" label="最大长度">
|
||||
<el-input-number
|
||||
v-model="form.MaxAnswerLength"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
:max="2000"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType === 'table'" label="最大行数">
|
||||
<el-input-number
|
||||
v-model="form.MaxQuestionCount"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
:max="10"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.ClinicalQuestionType === 'upload'" label="最大上传个数">
|
||||
<el-input-number v-model="form.ImageCount" controls-position="right" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
<el-form-item label="序号" prop="ShowOrder">
|
||||
<el-input-number
|
||||
v-model="form.ShowOrder"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateTrialClinicalQuestion, getTrialClinicalOtherQuestionList, getTrialClinicalGroupQuestionList, getClinicalCalculateQuestions } from '@/api/dictionary'
|
||||
export default {
|
||||
name: 'AddOrUpdateClinicalData',
|
||||
props: {
|
||||
clinicalId: {
|
||||
type: String,
|
||||
default() { return '' }
|
||||
},
|
||||
clinicalInfo: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() { return [] }
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default() { return '' }
|
||||
}
|
||||
},
|
||||
data() {
|
||||
var validateTypeVal = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error(this.$t('common:ruleMessage:specify')))
|
||||
} else {
|
||||
var arr = value.split('|')
|
||||
if (new Set(arr).size !== arr.length) {
|
||||
callback(new Error('选项不允许存在相同值'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
validateTypeVal: validateTypeVal,
|
||||
form: {
|
||||
Id: '',
|
||||
TrialClinicalId: null,
|
||||
DigitPlaces: null,
|
||||
QuestionName: '',
|
||||
QuestionEnName: '',
|
||||
ClinicalQuestionType: null,
|
||||
ValueType: '',
|
||||
Unit: '',
|
||||
TypeValue: '',
|
||||
ParentId: '',
|
||||
ParentTriggerValue: '',
|
||||
ShowOrder: 1,
|
||||
ClinicalQuestionShowEnum: 0,
|
||||
CalculateQuestions: [],
|
||||
IsRequired: 2,
|
||||
GroupName: '',
|
||||
GroupEnName: '',
|
||||
Remark: '',
|
||||
ImageCount: 1,
|
||||
QuestionType: null,
|
||||
MaxQuestionCount: 0,
|
||||
MaxAnswerLength: 0,
|
||||
IsCheckDate: false,
|
||||
LimitEdit: 0,
|
||||
GroupId: null,
|
||||
CustomCalculateMark: -1,
|
||||
RelevanceId: '',
|
||||
RelevanceValue: ''
|
||||
},
|
||||
rules: {
|
||||
ClinicalQuestionType: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
GroupId: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
LesionType: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
QuestionName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 300, message: '最大长度为 300' }],
|
||||
QuestionGenre: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
TypeValue: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 500, message: '最大长度为 500' }],
|
||||
DictionaryCode: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
IsCheckDate: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ClinicalQuestionShowEnum: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
IsRequired: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
DigitPlaces: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentTriggerValue: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
RelevanceId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
RelevanceValue: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
GroupName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }]
|
||||
},
|
||||
Questions: [],
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
parentOptions: [],
|
||||
parentTriggerValOptions: [],
|
||||
groupOptions: [],
|
||||
isParentExistGroup: false,
|
||||
lesionTypes: [],
|
||||
dicList: [],
|
||||
CriterionDictionaryList: [],
|
||||
isShow: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
this.getClinicalCalculateQuestions()
|
||||
},
|
||||
methods: {
|
||||
getClinicalCalculateQuestions() {
|
||||
getClinicalCalculateQuestions({
|
||||
TrialClinicalId: this.clinicalId,
|
||||
ClinicalQuestionType: 'time'
|
||||
}).then(res => {
|
||||
this.Questions = res.Result
|
||||
})
|
||||
},
|
||||
CustomCalculateMarkChange() {
|
||||
this.isShow = false
|
||||
console.log(this.form.CustomCalculateMark)
|
||||
if (this.form.CustomCalculateMark < 0) {
|
||||
this.form.CalculateQuestions = []
|
||||
return
|
||||
}
|
||||
if (this.form.CustomCalculateMark === 10) {
|
||||
this.form.CalculateQuestions = [
|
||||
{
|
||||
IsTable: false,
|
||||
QuestionId: null,
|
||||
TableQuestionId: null
|
||||
}]
|
||||
this.$nextTick(() => {
|
||||
this.isShow = true
|
||||
})
|
||||
return
|
||||
}
|
||||
if (this.form.CustomCalculateMark <= 4) {
|
||||
this.form.CalculateQuestions = [
|
||||
{
|
||||
IsTable: false,
|
||||
QuestionId: null,
|
||||
TableQuestionId: null
|
||||
}, {
|
||||
IsTable: false,
|
||||
QuestionId: null,
|
||||
TableQuestionId: null
|
||||
}
|
||||
]
|
||||
} else {
|
||||
this.form.CalculateQuestions = [
|
||||
{
|
||||
IsTable: true,
|
||||
QuestionId: null,
|
||||
TableQuestionId: null
|
||||
}
|
||||
]
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.isShow = true
|
||||
})
|
||||
},
|
||||
isRequiredChange(val, form) {
|
||||
if (val !== 1) {
|
||||
form.RelevanceId = ''
|
||||
form.RelevanceValue = ''
|
||||
}
|
||||
},
|
||||
async initForm() {
|
||||
await this.getGroupOptions()
|
||||
await this.getParentQuestions()
|
||||
await this.getBasicConfigSelect()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
if (k === 'CalculateQuestions' && this.data[k] !== undefined) {
|
||||
this.form[k] = JSON.parse(this.data[k])
|
||||
this.isShow = true
|
||||
} else {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.form.ParentId !== '' && this.form.ParentId !== null && this.form.GroupName !== '') {
|
||||
this.isParentExistGroup = true
|
||||
}
|
||||
if (this.form.ParentId) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.Id === this.form.ParentId
|
||||
})
|
||||
if (index !== -1) {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
if (this.form.RelevanceId) {
|
||||
var i = this.parentOptions.findIndex(item => {
|
||||
return item.Id === this.form.RelevanceId
|
||||
})
|
||||
if (i !== -1) {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.reParentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.form.Id) {
|
||||
if (this.list.length > 0) {
|
||||
let max = Math.max(...this.list.map(item=>item.ShowOrder))
|
||||
this.form.ShowOrder = max + 1
|
||||
}
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.clinicalDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
this.form.TrialClinicalId = this.clinicalId
|
||||
if (this.form.ClinicalQuestionType !== 'upload') {
|
||||
this.form.ImageCount = 0
|
||||
}
|
||||
var params = Object.assign({}, this.form)
|
||||
params.CalculateQuestions = JSON.stringify(this.form.CalculateQuestions)
|
||||
addOrUpdateTrialClinicalQuestion(params).then(res => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
getBasicConfigSelect() {
|
||||
this.dicList = this.$d
|
||||
|
||||
},
|
||||
getGroupOptions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
TrialClinicalId: this.clinicalId
|
||||
}
|
||||
getTrialClinicalGroupQuestionList(param).then(res => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
getParentQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
TrialClinicalId: this.clinicalId
|
||||
}
|
||||
getTrialClinicalOtherQuestionList(param).then(res => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
typeChange(val, data) {
|
||||
if (val !== 'select' && val !== 'radio') {
|
||||
}
|
||||
if (val === 'table') {
|
||||
data.IsRequired = 2
|
||||
} else {
|
||||
data.LesionType = null
|
||||
}
|
||||
data.TypeValue = ''
|
||||
data.ValueType = ''
|
||||
data.Unit = ''
|
||||
},
|
||||
isShowQuestionChange(val, form) {
|
||||
if (val === 2) {
|
||||
form.IsRequired = 2
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
} else {
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
}
|
||||
},
|
||||
parentQuestionChange(val, form) {
|
||||
console.log(val)
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.Id === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
var options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
} else {
|
||||
form.GroupName = ''
|
||||
form.GroupEnName = ''
|
||||
}
|
||||
form.ParentTriggerValue = ''
|
||||
},
|
||||
relevanceQuestionChange(val, form) {
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.Id === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
var options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.reParentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
form.RelevanceValue = ''
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,716 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-for="(qs,index) in questions" :key="index" v-loading="loading" class="lesions lesions_wrapper">
|
||||
<h4 v-if="qs.Type === 'group'" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ qs.GroupName }}
|
||||
</h4>
|
||||
<div class="lesion_list">
|
||||
<div v-for="item in qs.Childrens" v-show="!(isBaseLineTask && item.LesionType === 2) && !(isBaseLineTask && item.LesionType === 3)" :key="item.Id">
|
||||
<!-- <div v-for="item in qs.Childrens" :key="item.Id">-->
|
||||
<div v-if="item.Type === 'table'" class="flex-row">
|
||||
<div class="title">{{ item.QuestionName }}</div>
|
||||
<div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- @change="handleCollapseChange(qs.Childrens,item)" -->
|
||||
<el-collapse
|
||||
v-if="item.Type === 'table' && item.TableQuestions"
|
||||
v-model="activeName"
|
||||
accordion
|
||||
@change="handleCollapseChange"
|
||||
>
|
||||
<el-collapse-item
|
||||
v-for="(q,i) in item.TableQuestions.Answers"
|
||||
:key="i"
|
||||
:name="`${item.Id}_${q.RowIndex}`"
|
||||
>
|
||||
<template slot="title">
|
||||
<div style="width:300px;position: relative;" :style="{color:(activeName===item.Id+q.RowIndex?'#ffeb3b':'#fff')}">
|
||||
{{ getLesionName(item.OrderMark,q.RowIndex, qs.Childrens) }}
|
||||
<!-- <el-tooltip v-if="!item.TableQuestions.Answers[i].isLesionSaved" class="item" effect="dark" content="未保存" placement="bottom">-->
|
||||
<!-- <i class="el-icon-warning" style="color:red" />-->
|
||||
<!-- </el-tooltip>-->
|
||||
<el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) === 0" class="item" effect="dark" content="未保存" placement="bottom">
|
||||
<i class="el-icon-warning" style="color:red" />
|
||||
</el-tooltip>
|
||||
<el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) ===1 && item.LesionType !== 4" class="item" effect="dark" content="已更新,未保存" placement="bottom">
|
||||
<i class="el-icon-warning" style="color:#ff9800" />
|
||||
</el-tooltip>
|
||||
<div style="position: absolute;left: 60px;top: 2px;">
|
||||
<div style="display: flex;flex-direction: row;font-size: 10px;width:200px;">
|
||||
<div v-if="item.TableQuestions.Answers[i].lesionPart" style="margin-left:10px;margin-bottom:5px;">
|
||||
{{ item.TableQuestions.Answers[i].lesionPart }}
|
||||
</div>
|
||||
<div v-if="item.TableQuestions.Answers[i].lesionState" style="margin-left:10px;margin-bottom:5px;">
|
||||
{{ $fd('EvaluationOfState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<PCWG3QuestionsForm
|
||||
:ref="`${item.Id}_${q.RowIndex}`"
|
||||
:questions="item.TableQuestions.Questions"
|
||||
:answers="item.TableQuestions.Answers[i]"
|
||||
:lesion-type="item.LesionType"
|
||||
:order-mark="item.OrderMark"
|
||||
:table-questions="tableQuestions"
|
||||
:row-index="String(q.RowIndex)"
|
||||
:question-name="item.QuestionName"
|
||||
:parent-qs-id="item.Id"
|
||||
:visit-task-id="visitTaskId"
|
||||
:is-current-task="isCurrentTask"
|
||||
:reading-task-state="readingTaskState"
|
||||
:is-base-line-task="isBaseLineTask"
|
||||
@getReadingQuestionAndAnswer="getReadingQuestionAndAnswer"
|
||||
@determineExistsUnsavedLession="determineExistsUnsavedLession"
|
||||
@resetQuestions="resetQuestions"
|
||||
@close="close"
|
||||
/>
|
||||
</el-collapse-item>
|
||||
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DicomEvent from '../DicomEvent'
|
||||
import PCWG3QuestionsForm from './PCWG3QuestionsForm'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'PCWG3Questions',
|
||||
components: {
|
||||
PCWG3QuestionsForm
|
||||
},
|
||||
props: {
|
||||
questions: {
|
||||
type: Array,
|
||||
default() { return [] }
|
||||
},
|
||||
readingTaskStateParent: {
|
||||
type: Number,
|
||||
default() { return 0 }
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
activeName: null,
|
||||
isBaseLineTask: false,
|
||||
readingTaskState: 0,
|
||||
tableQuestions: [],
|
||||
unSaveTargets: [],
|
||||
activeItem: {
|
||||
activeRowIndex: null,
|
||||
activeCollapseId: null
|
||||
},
|
||||
visitTaskId: '',
|
||||
isFirstRender: false,
|
||||
isCurrentTask: false,
|
||||
TaskNum: null,
|
||||
BlindName: null,
|
||||
isMax: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList'])
|
||||
},
|
||||
watch: {
|
||||
readingTaskStateParent(v) {
|
||||
this.readingTaskState = v
|
||||
},
|
||||
activeName(v) {
|
||||
if (v) {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs[refName][0].questionForm && !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
DicomEvent.$emit('PGWC3Active')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
DicomEvent.$on('loadMeasurementList', async obj => {
|
||||
this.initPage(obj)
|
||||
})
|
||||
DicomEvent.$on('getAllUnSaveLesions', (callback) => {
|
||||
var list = this.getAllUnSaveLesions()
|
||||
callback(list)
|
||||
})
|
||||
DicomEvent.$on('setCollapseActive', measureData => {
|
||||
this.setCollapseActive(measureData)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
modifyMeasuredData(measureObj) {
|
||||
if (measureObj.questionInfo) {
|
||||
this.activeItem.activeCollapseId = measureObj.questionInfo.QuestionId
|
||||
this.activeItem.activeRowIndex = String(measureObj.questionInfo.RowIndex)
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
this.$refs[refName][0].setMeasureData(measureObj.measureData)
|
||||
}
|
||||
},
|
||||
setMeasuredData(measureData) {
|
||||
if (this.activeItem.activeCollapseId) {
|
||||
// 判断是否存在测量数据
|
||||
this.$nextTick(() => {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if ((this.$refs[refName][0].questionForm && this.$refs[refName][0].questionForm.MeasureData && measureData.data.uuid === this.$refs[refName][0].questionForm.MeasureData.data.uuid) || !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
this.$refs[refName][0].setMeasureData(measureData)
|
||||
} else {
|
||||
if (this.isBaseLineTask) {
|
||||
this.createNTTarget(measureData)
|
||||
} else {
|
||||
this.createNLTarget(measureData)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (this.isBaseLineTask) {
|
||||
this.createNTTarget(measureData)
|
||||
} else {
|
||||
this.createNLTarget(measureData)
|
||||
}
|
||||
}
|
||||
},
|
||||
createNTTarget(measureData) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 4)
|
||||
if (idx > -1) {
|
||||
this.addTarget(this.tableQuestions[idx], measureData)
|
||||
}
|
||||
},
|
||||
setCollapseActive(measureData) {
|
||||
if (measureData) {
|
||||
if (this.activeItem.activeRowIndex === measureData.RowIndex && this.activeItem.activeCollapseId === measureData.QuestionId) {
|
||||
return
|
||||
} else {
|
||||
this.activeItem.activeCollapseId = measureData.QuestionId
|
||||
this.activeItem.activeRowIndex = measureData.RowIndex
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
}
|
||||
}
|
||||
},
|
||||
// 创建新病灶
|
||||
createNLTarget(measureData) {
|
||||
var idx = this.tableQuestions.findIndex(item => item.LesionType === 2)
|
||||
var idx2 = this.tableQuestions.findIndex(item => item.LesionType === 3)
|
||||
if (idx > -1) {
|
||||
this.addTarget(this.tableQuestions[idx], measureData, this.tableQuestions[idx2])
|
||||
}
|
||||
},
|
||||
async addTarget(target, measureData, atarget) {
|
||||
var obj = { saveTypeEnum: 0 }
|
||||
// obj.RowIndex = target.TableQuestions.Answers.length + 1
|
||||
// var questions = target.TableQuestions.Questions.find(item => item.QuestionMark === 3)
|
||||
var questions2 = target.TableQuestions.Questions.find(item => item.QuestionMark === 9)
|
||||
var questions3 = target.TableQuestions.Questions.find(item => item.QuestionMark === 7)
|
||||
questions3 && (obj[questions3.Id] = 2)
|
||||
// if (questions) {
|
||||
// var maxIndex = this.getMaxRowIndex(target.TableQuestions.Answers)
|
||||
// if (maxIndex < 1 && !this.isBaseLineTask) {
|
||||
// maxIndex = this.getMaxRowIndex(atarget.TableQuestions.Answers)
|
||||
// }
|
||||
// obj.RowIndex = `${maxIndex + 1}.00`
|
||||
// obj[questions.Id] = `${target.OrderMark}${String(maxIndex + 1).padStart(2, '0')}`
|
||||
// }
|
||||
var maxIndex = this.getMaxRowIndex(target.TableQuestions.Answers)
|
||||
if (maxIndex < 1 && !this.isBaseLineTask) {
|
||||
maxIndex = this.getMaxRowIndex(atarget.TableQuestions.Answers)
|
||||
}
|
||||
obj.RowIndex = `${maxIndex + 1}.00`
|
||||
if (questions2) {
|
||||
obj[questions2.Id] = this.BlindName
|
||||
obj['BlindName'] = this.BlindName
|
||||
obj['TaskNum'] = this.TaskNum
|
||||
}
|
||||
// target.TableQuestions.Answers.push(obj)
|
||||
await store.dispatch('reading/addReadingQuestionAndAnswer', { lesionType: target.LesionType, visitTaskId: this.visitTaskId, lesionObj: obj })
|
||||
|
||||
this.activeItem.activeRowIndex = String(obj.RowIndex)
|
||||
this.activeItem.activeCollapseId = target.Id
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
this.$nextTick(() => {
|
||||
this.$refs[refName][0].setMeasureData(measureData)
|
||||
})
|
||||
},
|
||||
determineExistsUnsavedLession(callback) {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
var rowIndex = String(this.unSaveTargets[0].rowIndex)
|
||||
var questionId = this.unSaveTargets[0].questionId
|
||||
if (rowIndex === String(this.activeItem.activeRowIndex) && questionId === this.activeItem.activeCollapseId) {
|
||||
callback(true)
|
||||
// loading.close()
|
||||
return
|
||||
} else {
|
||||
this.$confirm(`病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许执行此操作!`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => { }
|
||||
})
|
||||
callback(false)
|
||||
// loading.close()
|
||||
return
|
||||
}
|
||||
}
|
||||
callback(true)
|
||||
// loading.close()
|
||||
return
|
||||
},
|
||||
getReadingQuestionAndAnswer() {
|
||||
return new Promise(async resolve => {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
await store.dispatch('reading/refreshReadingQuestionAndAnswer', { trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId }).then(() => {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
}
|
||||
this.getTableQuestions()
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
await store.dispatch('reading/refreshMeasuredData', this.visitTaskId)
|
||||
DicomEvent.$emit('getMeasureData')
|
||||
loading.close()
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
// getReadingQuestionAndAnswer() {
|
||||
// return new Promise(async resolve => {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
// await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId }).then(() => {
|
||||
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
// if (idx > -1) {
|
||||
// if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
// this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
// }
|
||||
// this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
// this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
// this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
// }
|
||||
// this.getTableQuestions()
|
||||
// })
|
||||
// await store.dispatch('reading/getMeasuredData', this.visitTaskId)
|
||||
// DicomEvent.$emit('getMeasureData')
|
||||
// loading.close()
|
||||
// resolve()
|
||||
// })
|
||||
// },
|
||||
getUnSaveTarget() {
|
||||
this.unSaveTargets = []
|
||||
this.isMax = false
|
||||
this.tableQuestions.map(item => {
|
||||
if (item.TableQuestions && item.TableQuestions.Answers && item.TableQuestions.Answers.length < item.MaxQuestionCount) {
|
||||
item.TableQuestions.Answers.map(t => {
|
||||
if (!t.RowId) {
|
||||
var lessionName = this.getLesionName(item.OrderMark, t.RowIndex)
|
||||
this.unSaveTargets.push({ lessionName: lessionName, rowIndex: t.RowIndex, questionId: item.Id })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isMax = true
|
||||
if (this.isBaseLineTask) {
|
||||
this.isMax = false
|
||||
}
|
||||
if (item.MaxQuestionCount === null) {
|
||||
this.isMax = false
|
||||
}
|
||||
}
|
||||
})
|
||||
return this.unSaveTargets
|
||||
},
|
||||
async resetQuestions(obj) {
|
||||
this.setQuestions(this.questions, obj)
|
||||
await store.dispatch('reading/setReadingQuestionAndAnswer', { questions: this.questions, visitTaskId: this.visitTaskId })
|
||||
this.getTableQuestions()
|
||||
},
|
||||
setQuestions(questions, obj) {
|
||||
questions.forEach(item => {
|
||||
if (item.Type === 'table' && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion
|
||||
item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan
|
||||
item.TableQuestions.Answers[idx].lesionPart = obj.lesionPart
|
||||
item.TableQuestions.Answers[idx].lesionLength = obj.lesionLength
|
||||
item.TableQuestions.Answers[idx].lesionShort = obj.lesionShort
|
||||
item.TableQuestions.Answers[idx].lesionState = obj.lesionState
|
||||
item.TableQuestions.Answers[idx].saveTypeEnum = obj.saveTypeEnum
|
||||
for (const i in obj.anwsers) {
|
||||
if (i === 'MeasureData' && obj.anwsers[i]) {
|
||||
item.TableQuestions.Answers[idx].InstanceId = obj.anwsers[i].instanceId
|
||||
item.TableQuestions.Answers[idx].SeriesId = obj.anwsers[i].seriesId
|
||||
item.TableQuestions.Answers[idx][i] = JSON.stringify(obj.anwsers[i])
|
||||
item.TableQuestions.Answers[idx].isDicomReading = !(obj.anwsers[i].IsDicomReading === false || obj.anwsers[i].IsDicomReading === 'False')
|
||||
} else {
|
||||
item.TableQuestions.Answers[idx][i] = String(obj.anwsers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestions(item.Childrens, obj)
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestions(questions) {
|
||||
questions.forEach(item => {
|
||||
if (item.Type === 'table' && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
this.$set(answerObj, 'loctation', this.getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj))
|
||||
this.$set(answerObj, 'lesionLength', this.getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj))
|
||||
this.$set(answerObj, 'lesionShort', this.getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj))
|
||||
var isLymphLesion = this.getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
|
||||
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
|
||||
this.$set(answerObj, 'isLymphLesion', isLymphLesion)
|
||||
this.$set(answerObj, 'isLesionSaved', true)
|
||||
|
||||
var lesionState = this.getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
|
||||
lesionState = !isNaN(parseInt(lesionState)) ? parseInt(lesionState) : ''
|
||||
this.$set(answerObj, 'lesionState', lesionState)
|
||||
if (answerObj.RowId) {
|
||||
this.$set(answerObj, 'saveTypeEnum', isNaN(parseInt(lesionState)) ? 1 : 2)
|
||||
} else {
|
||||
this.$set(answerObj, 'saveTypeEnum', 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getQuestions(item.Childrens)
|
||||
}
|
||||
})
|
||||
return questions
|
||||
},
|
||||
getTableQuestions() {
|
||||
this.tableQuestions = []
|
||||
this.questions.map(item => {
|
||||
if (item.Type === 'table') {
|
||||
this.tableQuestions.push(item)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getTableQuestionsChild(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
getTableQuestionsChild(obj) {
|
||||
obj.map(item => {
|
||||
if (item.Type === 'table') {
|
||||
this.tableQuestions.push(item)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getTableQuestionsChild(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
getLesionName(orderMark, rowIndex, qs) {
|
||||
var lessionName = ''
|
||||
var rowIndexArr = rowIndex.split('.')
|
||||
var x = parseInt(rowIndexArr[0])
|
||||
var y = parseInt(rowIndexArr[1])
|
||||
if (y > 0) {
|
||||
y = String.fromCharCode(parseInt(rowIndexArr[1]) - 1 + 65 + 32)
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}${y}`
|
||||
} else {
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}`
|
||||
}
|
||||
return lessionName
|
||||
},
|
||||
handleAdd(qs) {
|
||||
this.getUnSaveTarget()
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
this.$confirm(`病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许继续添加!`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!!qs.MaxQuestionCount && qs.MaxQuestionCount <= qs.TableQuestions.Answers.length) {
|
||||
this.$confirm(`${qs.QuestionName}个数最多不能超过${qs.MaxQuestionCount}个`, {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
} else {
|
||||
var obj = { saveTypeEnum: 0 }
|
||||
var idx2 = this.tableQuestions.findIndex(item => item.LesionType === 3)
|
||||
var maxIndex = this.getMaxRowIndex(qs.TableQuestions.Answers)
|
||||
if (maxIndex < 1) {
|
||||
maxIndex = this.getMaxRowIndex(this.tableQuestions[idx2].TableQuestions.Answers)
|
||||
}
|
||||
obj.RowIndex = `${maxIndex + 1}.00`
|
||||
qs.TableQuestions.Questions.forEach(item => {
|
||||
if (item.QuestionMark === 9) {
|
||||
obj[item.Id] = this.BlindName
|
||||
obj['BlindName'] = this.BlindName
|
||||
obj['TaskNum'] = this.TaskNum
|
||||
} else if (item.QuestionMark === 7) {
|
||||
console.log('状态')
|
||||
obj[item.Id] = 2
|
||||
} else {
|
||||
obj[item.Id] = ''
|
||||
}
|
||||
})
|
||||
qs.TableQuestions.Answers.push(obj)
|
||||
this.activeItem.activeRowIndex = String(obj.RowIndex)
|
||||
this.activeItem.activeCollapseId = qs.Id
|
||||
this.activeName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
}
|
||||
},
|
||||
getMaxRowIndex(answerList) {
|
||||
if (answerList.length > 0) {
|
||||
var arr = []
|
||||
answerList.forEach(item => {
|
||||
var rowIndex = item.RowIndex
|
||||
arr.push(parseInt(rowIndex))
|
||||
})
|
||||
var max = Math.max.apply(null, arr)
|
||||
return max
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
handleCollapseChange(val) {
|
||||
console.log(this.activeName)
|
||||
if (this.activeName) {
|
||||
var arr = this.activeName.split('_')
|
||||
this.activeItem.activeRowIndex = arr[1]
|
||||
this.activeItem.activeCollapseId = arr[0]
|
||||
this.$nextTick(() => {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (this.$refs[refName][0].questionForm.IsDicomReading !== false) {
|
||||
DicomEvent.$emit('imageLocation', { questionId: this.activeItem.activeCollapseId, rowIndex: this.activeItem.activeRowIndex, visitTaskId: this.visitTaskId, lesionName: this.$refs[refName][0].lesionName, lesionType: this.$refs[refName][0].lesionType })
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
}
|
||||
},
|
||||
getAllUnSaveLesions() {
|
||||
var arr = []
|
||||
console.log(this.tableQuestions)
|
||||
this.tableQuestions.map(item => {
|
||||
if (item.TableQuestions && item.TableQuestions.Answers) {
|
||||
item.TableQuestions.Answers.map(t => {
|
||||
const refName = `${item.Id}_${t.RowIndex}`
|
||||
if (this.$refs[refName] && this.$refs[refName][0] && this.$refs[refName][0].questionForm.saveTypeEnum !== 2) {
|
||||
var lessionName = this.getLesionName(item.OrderMark, t.RowIndex)
|
||||
arr.push({ lessionName: lessionName, rowIndex: t.RowIndex, questionId: item.Id })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return arr
|
||||
},
|
||||
initPage(obj) {
|
||||
console.log(this.questions)
|
||||
if (this.visitTaskId !== obj.visitTaskId) {
|
||||
this.visitTaskId = obj.visitTaskId
|
||||
this.taskBlindName = obj.taskBlindName
|
||||
this.activeName = ''
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
// this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
this.$emit('getECRFQuestions', obj)
|
||||
}
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
this.TaskNum = this.visitTaskList[idx].VisitTaskNum
|
||||
this.BlindName = this.visitTaskList[idx].TaskBlindName
|
||||
this.getTableQuestions()
|
||||
if (this.isFirstRender) {
|
||||
this.$nextTick(() => {
|
||||
this.tableQuestions.forEach(item => {
|
||||
item.TableQuestions.Answers.forEach(i => {
|
||||
var refName = `${item.Id}_${i.RowIndex}`
|
||||
this.$refs[refName][0].initForm()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!this.isFirstRender) {
|
||||
this.isFirstRender = true
|
||||
}
|
||||
},
|
||||
isCanActiveTool(toolName) {
|
||||
this.getUnSaveTarget()
|
||||
if (!this.activeName) {
|
||||
if (this.isMax) {
|
||||
return { isCanActiveTool: false, reason: `新病灶已到达最大数,无法添加` }
|
||||
}
|
||||
} else {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (this.$refs[refName][0].questionForm.MeasureData && this.isMax) {
|
||||
return { isCanActiveTool: false, reason: `新病灶已到达最大数,无法添加` }
|
||||
}
|
||||
}
|
||||
if (this.unSaveTargets.length > 0) {
|
||||
var rowIndex = String(this.unSaveTargets[0].rowIndex)
|
||||
var questionId = this.unSaveTargets[0].questionId
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
if (rowIndex === this.activeItem.activeRowIndex && questionId === this.activeItem.activeCollapseId && !this.$refs[refName][0].questionForm.MeasureData) {
|
||||
return this.checkToolCanActive(toolName)
|
||||
} else {
|
||||
return { isCanActiveTool: false, reason: `病灶${this.unSaveTargets[0].lessionName}信息未保存,不允许继续添加!` }
|
||||
}
|
||||
} else {
|
||||
if (this.activeItem.activeCollapseId) {
|
||||
return this.checkToolCanActive(toolName)
|
||||
} else {
|
||||
if (toolName === 'ArrowAnnotate' || toolName === 'Bidirectional' || toolName === 'Length') {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
} else {
|
||||
return { isCanActiveTool: false, reason: '' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
checkToolCanActive(toolName) {
|
||||
const refName = `${this.activeItem.activeCollapseId}_${this.activeItem.activeRowIndex}`
|
||||
var isLymphNodes = this.$refs[refName][0].getQuestionVal(2)
|
||||
isLymphNodes = !isNaN(parseInt(isLymphNodes)) ? parseInt(isLymphNodes) : null
|
||||
if (!this.$refs[refName][0].questionForm.MeasureData) {
|
||||
if (this.isBaseLineTask) {
|
||||
if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 1 && toolName !== 'Bidirectional') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结靶病灶需使用长短径测量工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 0 && toolName !== 'Length') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结靶病灶需使用长径测量工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结非靶病灶需使用长短径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结非靶病灶需使用长径测量工具或标注工具' }
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
} else {
|
||||
if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结靶病灶需使用长短径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 0 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结f非靶病灶需使用长径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结非靶病灶需使用长短径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 1 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结非靶病灶需使用长径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 2 && isLymphNodes === 1 && toolName !== 'Bidirectional' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '淋巴结新病灶需使用长短径测量工具或标注工具' }
|
||||
} else if (this.$refs[refName][0].lesionType === 2 && isLymphNodes === 0 && toolName !== 'Length' && toolName !== 'ArrowAnnotate') {
|
||||
return { isCanActiveTool: false, reason: '非淋巴结新病灶需使用长径测量工具或标注工具' }
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
}
|
||||
},
|
||||
async close(questionsObj) {
|
||||
if (questionsObj) {
|
||||
this.getReadingQuestionAndAnswer(questionsObj.visitTaskId)
|
||||
}
|
||||
this.activeItem.activeRowIndex = null
|
||||
this.activeItem.activeCollapseId = null
|
||||
this.activeName = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
.container{
|
||||
padding: 10px;
|
||||
}
|
||||
.title{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
.add-icon{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
border: 1px solid #938b8b;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #424242;
|
||||
|
||||
}
|
||||
.lesion_list{
|
||||
position: relative;
|
||||
}
|
||||
.el-collapse{
|
||||
border-bottom:none;
|
||||
>>>.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
>>>.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
padding-left: 5px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
>>>.el-collapse-item__wrap{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
}
|
||||
>>>.el-collapse-item__content{
|
||||
width:260px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
border: 1px solid #ffeb3b;
|
||||
z-index: 1;
|
||||
color: #ddd;
|
||||
padding: 5px;
|
||||
background-color:#1e1e1e;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
<template>
|
||||
<div id="tags-view-container" class="tags-view-container">
|
||||
<scroll-pane ref="scrollPane" class="tags-view-wrapper">
|
||||
<router-link
|
||||
v-for="tag in visitedViews"
|
||||
ref="tag"
|
||||
:key="tag.path"
|
||||
:class="isActive(tag)?'active':''"
|
||||
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||
tag="span"
|
||||
class="tags-view-item"
|
||||
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
|
||||
@contextmenu.prevent.native="openMenu(tag,$event)"
|
||||
>
|
||||
{{ tag.title }}
|
||||
<span
|
||||
v-if="!isAffix(tag)"
|
||||
class="el-icon-close"
|
||||
@click.prevent.stop="closeSelectedTag(tag)"
|
||||
/>
|
||||
</router-link>
|
||||
</scroll-pane>
|
||||
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
|
||||
<li @click="refreshSelectedTag(selectedTag)">Refresh</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">Close</li>
|
||||
<li @click="closeOthersTags">Close Others</li>
|
||||
<li @click="closeAllTags(selectedTag)">Close All</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScrollPane from './ScrollPane'
|
||||
import path from 'path'
|
||||
|
||||
export default {
|
||||
components: { ScrollPane },
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
top: 0,
|
||||
left: 0,
|
||||
selectedTag: {},
|
||||
affixTags: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visitedViews() {
|
||||
return this.$store.state.tagsView.visitedViews
|
||||
}
|
||||
// routes() {
|
||||
// return this.$store.state.permission.routes
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.addTags()
|
||||
this.moveToCurrentTag()
|
||||
},
|
||||
visible(value) {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', this.closeMenu)
|
||||
} else {
|
||||
document.body.removeEventListener('click', this.closeMenu)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initTags()
|
||||
this.addTags()
|
||||
},
|
||||
methods: {
|
||||
isActive(route) {
|
||||
return route.path === this.$route.path
|
||||
},
|
||||
isAffix(tag) {
|
||||
return tag.meta && tag.meta.affix
|
||||
},
|
||||
filterAffixTags(routes, basePath = '/') {
|
||||
let tags = []
|
||||
// 判断是否为空,否则控制台会报错
|
||||
if (this.routes) {
|
||||
routes.forEach(route => {
|
||||
if (route.meta && route.meta.affix) {
|
||||
const tagPath = path.resolve(basePath, route.path)
|
||||
tags.push({
|
||||
fullPath: tagPath,
|
||||
path: tagPath,
|
||||
name: route.name,
|
||||
meta: { ...route.meta }
|
||||
})
|
||||
}
|
||||
if (route.children) {
|
||||
const tempTags = this.filterAffixTags(route.children, route.path)
|
||||
if (tempTags.length >= 1) {
|
||||
tags = [...tags, ...tempTags]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return tags
|
||||
},
|
||||
initTags() {
|
||||
const affixTags = (this.affixTags = this.filterAffixTags(this.routes))
|
||||
for (const tag of affixTags) {
|
||||
// Must have tag name
|
||||
if (tag.name) {
|
||||
this.$store.dispatch('tagsView/addVisitedView', tag)
|
||||
}
|
||||
}
|
||||
},
|
||||
addTags() {
|
||||
const { name } = this.$route
|
||||
if (name) {
|
||||
this.$store.dispatch('tagsView/addView', this.$route)
|
||||
}
|
||||
return false
|
||||
},
|
||||
moveToCurrentTag() {
|
||||
const tags = this.$refs.tag
|
||||
this.$nextTick(() => {
|
||||
for (const tag of tags) {
|
||||
if (tag.to.path === this.$route.path) {
|
||||
this.$refs.scrollPane.moveToTarget(tag)
|
||||
// when query is different then update
|
||||
if (tag.to.fullPath !== this.$route.fullPath) {
|
||||
this.$store.dispatch('tagsView/updateVisitedView', this.$route)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
refreshSelectedTag(view) {
|
||||
this.$store.dispatch('tagsView/delCachedView', view).then(() => {
|
||||
const { fullPath } = view
|
||||
this.$nextTick(() => {
|
||||
this.$router.replace({
|
||||
path: '/redirect' + fullPath
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
closeSelectedTag(view) {
|
||||
this.$store
|
||||
.dispatch('tagsView/delView', view)
|
||||
.then(({ visitedViews }) => {
|
||||
if (this.isActive(view)) {
|
||||
this.toLastView(visitedViews, view)
|
||||
}
|
||||
})
|
||||
},
|
||||
closeOthersTags() {
|
||||
this.$router.push(this.selectedTag)
|
||||
this.$store
|
||||
.dispatch('tagsView/delOthersViews', this.selectedTag)
|
||||
.then(() => {
|
||||
this.moveToCurrentTag()
|
||||
})
|
||||
},
|
||||
closeAllTags(view) {
|
||||
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
|
||||
if (this.affixTags.some(tag => tag.path === view.path)) {
|
||||
return
|
||||
}
|
||||
this.toLastView(visitedViews, view)
|
||||
})
|
||||
},
|
||||
toLastView(visitedViews, view) {
|
||||
const latestView = visitedViews.slice(-1)[0]
|
||||
if (latestView) {
|
||||
this.$router.push(latestView.fullPath)
|
||||
} else {
|
||||
// now the default is to redirect to the home page if there is no tags-view,
|
||||
// you can adjust it according to your needs.
|
||||
if (view.name === 'Dashboard') {
|
||||
// to reload home page
|
||||
this.$router.replace({ path: '/redirect' + view.fullPath })
|
||||
} else {
|
||||
this.$router.push('/')
|
||||
}
|
||||
}
|
||||
},
|
||||
openMenu(tag, e) {
|
||||
const menuMinWidth = 105
|
||||
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
|
||||
const offsetWidth = this.$el.offsetWidth // container width
|
||||
const maxLeft = offsetWidth - menuMinWidth // left boundary
|
||||
const left = e.clientX - offsetLeft + 15 // 15: margin right
|
||||
|
||||
if (left > maxLeft) {
|
||||
this.left = maxLeft
|
||||
} else {
|
||||
this.left = left
|
||||
}
|
||||
|
||||
this.top = e.clientY
|
||||
this.visible = true
|
||||
this.selectedTag = tag
|
||||
},
|
||||
closeMenu() {
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tags-view-container {
|
||||
height: 34px;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #d8dce5;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
|
||||
.tags-view-wrapper {
|
||||
.tags-view-item {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
border: 1px solid #d8dce5;
|
||||
color: #495060;
|
||||
background: #fff;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
margin-left: 5px;
|
||||
margin-top: 4px;
|
||||
&:first-of-type {
|
||||
margin-left: 15px;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 15px;
|
||||
}
|
||||
&.active {
|
||||
background-color: #42b983;
|
||||
color: #fff;
|
||||
border-color: #42b983;
|
||||
&::before {
|
||||
content: "";
|
||||
background: #fff;
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.contextmenu {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
z-index: 3000;
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
padding: 5px 0;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 7px 16px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
//reset element css of el-icon-close
|
||||
.tags-view-wrapper {
|
||||
.tags-view-item {
|
||||
.el-icon-close {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: 2px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transform-origin: 100% 50%;
|
||||
&:before {
|
||||
transform: scale(0.6);
|
||||
display: inline-block;
|
||||
vertical-align: -3px;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #b4bccc;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,407 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="taskAllocationRuleDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
>
|
||||
<div>
|
||||
<div style="line-height: 32px;margin-bottom: 10px;">
|
||||
当前项目阅片模式为:
|
||||
<el-tag type="primary">{{ $fd('ReadingMethod', readingType) }}</el-tag>
|
||||
</div>
|
||||
<div v-if="readingType === 1" style="line-height: 32px;margin-bottom: 10px;">
|
||||
阅片人(R1):
|
||||
<el-select v-model="form.R1" clearable @change="$forceUpdate()" :disabled="!!q.find(v => v.ArmEnum === 0)" size="mini">
|
||||
<el-option v-for="item of DoctorSelectList.R1" :key="`R1${item.DoctorUserId}`" v-if="form.O1 !== item.DoctorUserId && form.AD !== item.DoctorUserId && form.R2 !== item.DoctorUserId && !q.find(v => v.DoctorUser.UserId === item.DoctorUserId) || !!q.find(v => v.ArmEnum === 0)" :label="`${item.UserName}(${item.FullName})`" :value="item.DoctorUserId" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div v-if="readingType === 2" style="line-height: 32px;margin-bottom: 10px;">
|
||||
阅片人(R1):
|
||||
<el-select v-model="form.R1" clearable @change="$forceUpdate()" :disabled="!!q.find(v => v.ArmEnum === 1)" size="mini">
|
||||
<el-option v-for="item of DoctorSelectList.R1" :key="`R1${item.DoctorUserId}`" v-if="form.O1 !== item.DoctorUserId && form.AD !== item.DoctorUserId && form.R2 !== item.DoctorUserId && !q.find(v => v.DoctorUser.UserId === item.DoctorUserId) || !!q.find(v => v.ArmEnum === 1)" :label="`${item.UserName}(${item.FullName})`" :value="item.DoctorUserId" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div v-if="readingType === 2" style="line-height: 32px;margin-bottom: 10px;">
|
||||
阅片人(R2):
|
||||
<el-select v-model="form.R2" clearable @change="$forceUpdate()" :disabled="!!q.find(v => v.ArmEnum === 2)" size="mini">
|
||||
<el-option v-for="item of DoctorSelectList.R2" :key="`R2${item.DoctorUserId}`" v-if="form.O1 !== item.DoctorUserId && form.R1 !== item.DoctorUserId && form.AD !== item.DoctorUserId && !q.find(v => v.DoctorUser.UserId === item.DoctorUserId) || !!q.find(v => v.ArmEnum === 2)" :label="`${item.UserName}(${item.FullName})`" :value="item.DoctorUserId" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="line-height: 32px;margin-bottom: 10px;">
|
||||
裁判(AD):
|
||||
<el-select v-model="form.AD" clearable @change="$forceUpdate()" :disabled="!!q.find(v => v.ArmEnum === 3)" size="mini">
|
||||
<el-option v-for="item of DoctorSelectList.AD" :key="`AD${item.DoctorUserId}`" v-if="form.O1 !== item.DoctorUserId && form.R1 !== item.DoctorUserId && form.R2 !== item.DoctorUserId && !q.find(v => v.DoctorUser.UserId === item.DoctorUserId) || !!q.find(v => v.ArmEnum === 3)" :label="`${item.UserName}(${item.FullName})`" :value="item.DoctorUserId" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div style="line-height: 32px;margin-bottom: 10px;">
|
||||
肿瘤阅片人(O1):
|
||||
<el-select v-model="form.O1" clearable @change="$forceUpdate()" :disabled="!!q.find(v => v.ArmEnum === 4)" size="mini">
|
||||
<el-option v-for="item of DoctorSelectList.O1" :key="`O1${item.DoctorUserId}`" v-if="form.AD !== item.DoctorUserId && form.R1 !== item.DoctorUserId && form.R2 !== item.DoctorUserId && !q.find(v => v.DoctorUser.UserId === item.DoctorUserId) || !!q.find(v => v.ArmEnum === 4)" :label="`${item.UserName}(${item.FullName})`" :value="item.DoctorUserId" />
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
border
|
||||
:data="list"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片人"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ `${scope.row.DoctorUser.UserName}(${scope.row.DoctorUser.FullName})` }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanSubjectCount"
|
||||
label="计划受试者数量"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="AssignedSubjectCount"
|
||||
label="已分配受试者数量"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片类型"
|
||||
min-width="260"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="item of scope.row.ReadingCategoryList">
|
||||
<el-tag v-if="item === 1" type="primary">{{ $fd('ReadingCategory', item) + '&' + $fd('ReadingCategory', 2) }}</el-tag>
|
||||
<el-tag v-if="item === 4" type="danger">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
<el-tag v-if="item === 5" type="warning">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="WaitDealAllTaskCount"
|
||||
label="待处理任务量(全平台)"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="WaitDealTrialTaskCount"
|
||||
label="待处理任务量(项目)"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="访视平均阅片时间(去除离群值后的)"
|
||||
min-width="260"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
label="状态"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="!scope.row.IsEnable" type="danger">{{ $fd('IsEnable', scope.row.IsEnable) }}</el-tag>
|
||||
<el-tag v-else>{{ $fd('IsEnable', scope.row.IsEnable) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Note"
|
||||
label="备注"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="loading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
关闭
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" :loading="loading" style="margin-top: 10px;" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSubjectAssignAndTaskStatList, batchAssignDoctorToSubject, getDoctorSubjectStat, getDoctorSelectList} from '@/api/trials/reading'
|
||||
|
||||
export default {
|
||||
name: 'ManualAllocationTable',
|
||||
props: {
|
||||
TrialReadingCriterionId: {
|
||||
type: String,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
SubjectAssignSelectList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
// readingType: {
|
||||
// type: Number,
|
||||
// default() {
|
||||
// return 0
|
||||
// }
|
||||
// }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
TrialId: this.$route.query.trialId,
|
||||
form: {
|
||||
R0: null,
|
||||
R1: null,
|
||||
R2: null,
|
||||
AD: null,
|
||||
O1: null
|
||||
},
|
||||
DoctorSelectList: {
|
||||
R1: [],
|
||||
R2: [],
|
||||
AD: [],
|
||||
O1: [],
|
||||
},
|
||||
list: [],
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
q: [],
|
||||
readingType: null,
|
||||
isShowInfo: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.TrialId = this.$route.query.trialId
|
||||
this.getDoctorSubjectStat()
|
||||
var arr = []
|
||||
arr.push(this.getDoctorSelectList(1))
|
||||
arr.push(this.getDoctorSelectList(2))
|
||||
arr.push(this.getDoctorSelectList(4))
|
||||
arr.push(this.getDoctorSelectList(5))
|
||||
var q = []
|
||||
if (Object.keys(this.data).length && this.data.SubjectId) {
|
||||
} else {
|
||||
this.SubjectAssignSelectList.forEach(v => {
|
||||
v.NowDoctorUserList.forEach(v1 => {
|
||||
q.push(v1)
|
||||
})
|
||||
this.q = q
|
||||
})
|
||||
}
|
||||
console.log(q)
|
||||
Promise.all(arr).then(() => {
|
||||
if (Object.keys(this.data).length && this.data.SubjectId) {
|
||||
this.form.R0 = this.findDoctorUser(this.data.NowDoctorUserList, 0).DoctorUser ? this.findDoctorUser(this.data.NowDoctorUserList, 0).DoctorUser.UserId : null
|
||||
this.form.R1 = this.findDoctorUser(this.data.NowDoctorUserList, 1).DoctorUser ? this.findDoctorUser(this.data.NowDoctorUserList, 1).DoctorUser.UserId : null
|
||||
this.form.R2 = this.findDoctorUser(this.data.NowDoctorUserList, 2).DoctorUser ? this.findDoctorUser(this.data.NowDoctorUserList, 2).DoctorUser.UserId : null
|
||||
this.form.AD = this.findDoctorUser(this.data.NowDoctorUserList, 3).DoctorUser ? this.findDoctorUser(this.data.NowDoctorUserList, 3).DoctorUser.UserId : null
|
||||
this.form.O1 = this.findDoctorUser(this.data.NowDoctorUserList, 4).DoctorUser ? this.findDoctorUser(this.data.NowDoctorUserList, 4).DoctorUser.UserId : null
|
||||
this.data.NowDoctorUserList.forEach(v1 => {
|
||||
q.push(v1)
|
||||
})
|
||||
this.q = q
|
||||
} else {
|
||||
var userList = {
|
||||
R0: [],
|
||||
R1: [],
|
||||
R2: [],
|
||||
AD: [],
|
||||
O1: []
|
||||
}
|
||||
this.SubjectAssignSelectList.forEach(v1 => {
|
||||
v1.NowDoctorUserList.forEach(v => {
|
||||
if (v.ArmEnum === 0) {
|
||||
userList.R0.push(v)
|
||||
}
|
||||
if (v.ArmEnum === 1) {
|
||||
userList.R1.push(v)
|
||||
}
|
||||
if (v.ArmEnum === 2) {
|
||||
userList.R2.push(v)
|
||||
}
|
||||
if (v.ArmEnum === 3) {
|
||||
userList.AD.push(v)
|
||||
}
|
||||
if (v.ArmEnum === 4) {
|
||||
userList.O1.push(v)
|
||||
}
|
||||
})
|
||||
})
|
||||
var isShowInfo = {}
|
||||
for (var key in userList) {
|
||||
var itemList = userList[key]
|
||||
var id
|
||||
isShowInfo[key] = this.checkArrayObjectValueRepeat(itemList, 'DoctorUserId')
|
||||
}
|
||||
this.isShowInfo = isShowInfo
|
||||
if (!isShowInfo.R0) {
|
||||
this.form.R0 = this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 0).DoctorUser ? this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 0).DoctorUser.UserId : null
|
||||
}
|
||||
if (!isShowInfo.R1) {
|
||||
this.form.R1 = this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 1).DoctorUser ? this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 1).DoctorUser.UserId : null
|
||||
}
|
||||
if (!isShowInfo.R2) {
|
||||
this.form.R2 = this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 2).DoctorUser ? this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 2).DoctorUser.UserId : null
|
||||
}
|
||||
if (!isShowInfo.AD) {
|
||||
this.form.AD = this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 3).DoctorUser ? this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 3).DoctorUser.UserId : null
|
||||
}
|
||||
if (!isShowInfo.O1) {
|
||||
this.form.O1 = this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 4).DoctorUser ? this.findDoctorUser(this.SubjectAssignSelectList[0].NowDoctorUserList, 4).DoctorUser.UserId : null
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
checkArrayObjectValueRepeat(dataArr, key) {
|
||||
console.log(dataArr)
|
||||
var a = null
|
||||
var b = false
|
||||
console.log(this.SubjectAssignSelectList.length)
|
||||
if (this.SubjectAssignSelectList.length === 1) {
|
||||
return false
|
||||
}
|
||||
dataArr.forEach((v,i) => {
|
||||
if(i === 0){
|
||||
a = v[key]
|
||||
}
|
||||
if (v[key] !== a) {
|
||||
b = true
|
||||
}
|
||||
if (dataArr.length === 1) {
|
||||
b = true
|
||||
}
|
||||
})
|
||||
return b
|
||||
},
|
||||
findDoctorUser(list, type) {
|
||||
var a
|
||||
if (list.length > 0) {
|
||||
a = list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) ? list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) : {
|
||||
DoctorUser: null
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
getDoctorSelectList(ReadingCategory) {
|
||||
return new Promise(resolve => {
|
||||
getDoctorSelectList({
|
||||
TrialId: this.$route.query.trialId,
|
||||
ReadingCategory: ReadingCategory,
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||
}).then(res => {
|
||||
switch (ReadingCategory) {
|
||||
case 1:
|
||||
this.$set(this.DoctorSelectList, 'R1', res.Result)
|
||||
break;
|
||||
case 2:
|
||||
this.$set(this.DoctorSelectList, 'R2', res.Result)
|
||||
break;
|
||||
case 4:
|
||||
this.$set(this.DoctorSelectList, 'AD', res.Result)
|
||||
break;
|
||||
case 5:
|
||||
this.$set(this.DoctorSelectList, 'O1', res.Result)
|
||||
break;
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
getDoctorSubjectStat() {
|
||||
this.loading = true
|
||||
getDoctorSubjectStat(this.TrialId, this.TrialReadingCriterionId).then(res => {
|
||||
this.readingType = res.OtherInfo.ReadingType
|
||||
this.list = res.Result
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
save() {
|
||||
var DoctorArmList = []
|
||||
if (this.form.R0) {
|
||||
DoctorArmList.push({
|
||||
ArmEnum: 0,
|
||||
DoctorUserId: this.form.R0
|
||||
})
|
||||
}
|
||||
if (this.form.R1) {
|
||||
DoctorArmList.push({
|
||||
ArmEnum: 1,
|
||||
DoctorUserId: this.form.R1
|
||||
})
|
||||
}
|
||||
if (this.form.R2) {
|
||||
DoctorArmList.push({
|
||||
ArmEnum: 2,
|
||||
DoctorUserId: this.form.R2
|
||||
})
|
||||
}
|
||||
if (this.form.AD) {
|
||||
DoctorArmList.push({
|
||||
ArmEnum: 3,
|
||||
DoctorUserId: this.form.AD
|
||||
})
|
||||
}
|
||||
if (this.form.O1) {
|
||||
DoctorArmList.push({
|
||||
ArmEnum: 4,
|
||||
DoctorUserId: this.form.O1
|
||||
})
|
||||
}
|
||||
var params = {
|
||||
TrialId: this.TrialId,
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId,
|
||||
SubjectIdList: this.SubjectAssignSelectList.map(v => v.SubjectId),
|
||||
DoctorArmList: DoctorArmList
|
||||
}
|
||||
this.loading = true
|
||||
batchAssignDoctorToSubject(params).then(res => {
|
||||
this.$message.success('保存成功')
|
||||
this.loading = false
|
||||
this.$emit('getList')
|
||||
this.close()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
close() { this.$emit('close') }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,816 @@
|
|||
<template>
|
||||
<div class="criterion-form-item">
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
style="font-weight: bold;font-size: 16px;margin: 5px 0px;color:#fff;"
|
||||
>
|
||||
{{ question.GroupName }}
|
||||
</div>
|
||||
<div
|
||||
v-if=" question.Type==='table'"
|
||||
style="font-weight: bold;font-size: 14px;margin: 5px 0px;"
|
||||
>
|
||||
<div style="display: flex;justify-content: space-between;align-items: center;color:#fff;margin: 10px 0 5px">
|
||||
<span>{{ question.QuestionName }}</span>
|
||||
<el-button size="mini" v-if="readingTaskState<2" @click="openAddTableCol(question)">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="questionForm[question.Id]">
|
||||
<el-table-column
|
||||
:prop="item.Id"
|
||||
:label="item.QuestionName"
|
||||
:key="item.Id"
|
||||
v-for="item of question.TableQuestions.Questions"
|
||||
show-overflow-tooltip
|
||||
:render-header="renderHeader"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="item.Type === 'upload'">
|
||||
{{scope.row[item.Id] === '' ? '' : scope.row[item.Id].split('|').length}}
|
||||
</span>
|
||||
<span v-else-if="item.Type === 'number'">
|
||||
{{scope.row[item.Id] ? parseFloat(scope.row[item.Id]).toFixed(digitPlaces) : null}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{scope.row[item.Id]}}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
show-overflow-tooltip
|
||||
width="100px"
|
||||
v-if="readingTaskState < 2"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openAddTableCol(question, scope.$index)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button type="text" size="mini" v-if="scope.row.IsCurrentTaskAdd === 'True' || !question.IsCopyLesions || IsBaseline" @click="deleteTableCol(question, scope.$index)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(questionForm[question.ParentId])) || question.ShowQuestion===0"
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (question.RelevanceValueList.includes(questionForm[question.RelevanceId])))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: '请注明', trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
|
||||
>
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="question.TableQuestionType === 2"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
clearable
|
||||
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[question.DataTableColumn]"
|
||||
:value="item[question.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
|
||||
<!-- 自动计算 -->
|
||||
<!-- :precision="2" :step="0.1" :max="10" -->
|
||||
<el-input
|
||||
v-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
@input="value=value.replace(/^\D*(\d*(?:.\d{0,2})?).*$/g, '$1')"
|
||||
disabled
|
||||
/>
|
||||
<!-- 自增 -->
|
||||
<el-input
|
||||
v-if="question.Type==='increment'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
/>
|
||||
<!-- 数值 -->
|
||||
<!-- :precision="2" :step="0.1" :max="10" -->
|
||||
|
||||
<el-input
|
||||
type="number"
|
||||
v-if="question.Type === 'number' && question.DataSource !== 1"
|
||||
@change="((val)=>{formItemNumberChange(val, question)})"
|
||||
onblur="value=parseInt(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
v-model="questionForm[question.Id]"
|
||||
>
|
||||
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="question.ValueType === 2">%</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
type="number"
|
||||
v-if="question.Type === 'number' && question.DataSource === 1"
|
||||
onblur="value=parseInt(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
:disabled="question.DataSource === 1"
|
||||
v-model="questionForm[question.Id]"
|
||||
>
|
||||
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="question.ValueType === 2">%</template>
|
||||
</el-input>
|
||||
<!-- 上传图像 -->
|
||||
<el-upload
|
||||
v-if="question.Type==='upload'"
|
||||
:action="accept"
|
||||
:limit="question.ImageCount"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="uploadScreenshot"
|
||||
list-type="picture-card"
|
||||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
:class="{disabled:fileList.length >= question.ImageCount}"
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="file.url"
|
||||
alt=""
|
||||
>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</el-upload>
|
||||
<el-dialog
|
||||
v-if="question.Type==='upload'"
|
||||
append-to-body
|
||||
:visible.sync="imgVisible"
|
||||
width="600px"
|
||||
>
|
||||
<el-image :src="imageUrl" width="100%">
|
||||
<div slot="placeholder" class="image-slot">
|
||||
加载中<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="question.Childrens && question.Childrens.length>0 && question.Type !== 'table'">
|
||||
<CustomizeQuestionFormItem
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:IsBaseline="IsBaseline"
|
||||
:reading-task-state="readingTaskState"
|
||||
:question-form="questionForm"
|
||||
:visit-task-id="visitTaskId"
|
||||
:criterion-id="criterionId"
|
||||
:CalculationList="CalculationList"
|
||||
@formItemNumberChange="formItemNumberChange"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
</template>
|
||||
<base-model :config="addOrEdit"
|
||||
class="my_dialog"
|
||||
:close-on-click-modal="false"
|
||||
width="400px"
|
||||
append-to-body
|
||||
>
|
||||
<template slot="dialog-body">
|
||||
<el-form
|
||||
ref="tableQsForm"
|
||||
:model="QuestionsForm"
|
||||
v-loading="loading"
|
||||
size="small"
|
||||
>
|
||||
<QuestionTableFormItem
|
||||
v-for="(item) in QuestionsList"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:IsBaseline="IsBaseline"
|
||||
:reading-task-state="readingTaskState"
|
||||
:question-form="QuestionsForm"
|
||||
:visit-task-id="visitTaskId"
|
||||
:criterion-id="criterionId"
|
||||
:type="addOrEdit.type"
|
||||
:CalculationList="CalculationList"
|
||||
@formItemTableNumberChange="formItemTableNumberChange"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
@setFormTableItemData="setFormTableItemData"
|
||||
/>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
size="small"
|
||||
@click="addOrEdit.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" class="my_upload_btn" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadReadingAnswerImage, getTrialOrganList, deleteReadingRowAnswer, getCustomTableQuestionPreview, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials'
|
||||
import QuestionTableFormItem from './CustomizeQuestionTableFormItem'
|
||||
import BaseModel from '@/components/BaseModel'
|
||||
import DicomEvent from './../components/DicomEvent'
|
||||
export default {
|
||||
name: 'CustomizeQuestionFormItem',
|
||||
components: { QuestionTableFormItem, BaseModel },
|
||||
props: {
|
||||
IsBaseline: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
criterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
CalculationList: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addOrEdit: { visible: false, title: '', width: '400px' },
|
||||
fileList: [],
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: [],
|
||||
organList: [],
|
||||
QuestionsList: [],
|
||||
QuestionsForm: {},
|
||||
AnswersList: [],
|
||||
loading: false,
|
||||
RowIndex: 0,
|
||||
RowId: null,
|
||||
digitPlaces: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v, oldv) {
|
||||
try {
|
||||
if (!v[this.question.Id] || !oldv[this.question.Id]) return
|
||||
} catch (e) {
|
||||
}
|
||||
this.formItemNumberChange(this.question.Id, false)
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0
|
||||
if (this.question.Type === 'upload') {
|
||||
if (this.questionForm[this.question.Id]) {
|
||||
this.urls = this.questionForm[this.question.Id].split('|')
|
||||
this.fileList = []
|
||||
this.urls.map(url => {
|
||||
this.fileList.push({ name: '', url: `/api/${url}` })
|
||||
})
|
||||
}
|
||||
}
|
||||
if (this.question.Type === 'table') {
|
||||
// this.getQuestionCalculateRelation()
|
||||
if (this.questionForm[this.question.Id]) {
|
||||
this.QuestionsForm = {}
|
||||
this.question.TableQuestions.Questions.forEach(v => {
|
||||
if (v.Type === 'number') {
|
||||
this.$set(this.QuestionsForm, v.Id, 0)
|
||||
} else {
|
||||
this.$set(this.QuestionsForm, v.Id, '')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteTableCol(row, index) {
|
||||
console.log(row)
|
||||
this.$confirm('确定要删除该行表格问题吗?').then(() => {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var param = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
questionId: row.Id,
|
||||
rowId: this.questionForm[row.Id][index].RowId
|
||||
}
|
||||
deleteReadingRowAnswer(param)
|
||||
.then(async res => {
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success('删除成功')
|
||||
DicomEvent.$emit('reGetQuestionAnswer')
|
||||
}
|
||||
loading.close()
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
})
|
||||
})
|
||||
|
||||
},
|
||||
setFormTableItemData(id, url) {
|
||||
this.$set(this.QuestionsForm, id, url)
|
||||
},
|
||||
handleSave() {
|
||||
console.log(this.QuestionsForm)
|
||||
this.$refs.tableQsForm.validate(valid => {
|
||||
if (!valid) return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var answers = []
|
||||
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
|
||||
for (const k in this.QuestionsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
console.log(this.QuestionsForm)
|
||||
answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.addOrEdit.type === 'edit') {
|
||||
var params = {
|
||||
questionId: this.question.Id,
|
||||
RowIndex: parseInt(this.QuestionsForm.RowIndex),
|
||||
RowId: this.QuestionsForm.RowId,
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$route.query.trialId,
|
||||
answerList: answers,
|
||||
}
|
||||
} else {
|
||||
var params = {
|
||||
questionId: this.question.Id,
|
||||
RowIndex: this.questionForm[this.question.Id].length + 1,
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$route.query.trialId,
|
||||
answerList: answers,
|
||||
}
|
||||
this.QuestionsForm.RowIndex = this.questionForm[this.question.Id].length + 1
|
||||
}
|
||||
submitTableQuestion(params).then(async res => {
|
||||
this.$message.success('保存成功!')
|
||||
this.QuestionsForm.RowId = res.Result.RowId
|
||||
this.save()
|
||||
loading.close()
|
||||
}).catch(() => { loading.close() })
|
||||
})
|
||||
},
|
||||
renderHeader(h, obj) {
|
||||
let span = document.createElement('span')
|
||||
span.style.fontSize = '14px'
|
||||
span.innerText = obj.column.label
|
||||
document.body.appendChild(span)
|
||||
obj.column.realWidth = span.getBoundingClientRect().width + 40
|
||||
document.body.removeChild(span)
|
||||
return h('span', obj.column.label)
|
||||
},
|
||||
getQuestionCalculateRelation() {
|
||||
getQuestionCalculateRelation({
|
||||
TrialReadingCriterionId: this.criterionId,
|
||||
ReadingQuestionId: this.question.Id
|
||||
}).then(res => {
|
||||
this.CalculationList = res.Result
|
||||
})
|
||||
},
|
||||
save() {
|
||||
console.log(this.$refs.tableQsForm, this.QuestionsForm)
|
||||
this.$refs['tableQsForm'].validate((valid) => {
|
||||
console.log(valid)
|
||||
if (!valid) return
|
||||
if (this.addOrEdit.type === 'add') {
|
||||
this.AnswersList.push(this.QuestionsForm)
|
||||
} else {
|
||||
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
|
||||
this.AnswersList.splice(index, 1, this.QuestionsForm)
|
||||
}
|
||||
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList})
|
||||
this.formItemNumberChange(this.question.Id, true)
|
||||
this.addOrEdit.visible = false
|
||||
})
|
||||
},
|
||||
logic(rules, num = 0) {
|
||||
try {
|
||||
if (rules.CalculateQuestionList.length === 0) {
|
||||
return false
|
||||
}
|
||||
rules.CalculateQuestionList.forEach((o, i) => {
|
||||
if (i === 0) {
|
||||
if (rules.CustomCalculateMark > 4) {
|
||||
switch (rules.CustomCalculateMark) {
|
||||
case 5:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num *= parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 6:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num += parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 7:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num += parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
|
||||
break;
|
||||
case 8:
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.max(...arr)
|
||||
break;
|
||||
case 9:
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.min(...arr)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
num = parseFloat(this.questionForm[o.TableQuestionId])
|
||||
}
|
||||
} else {
|
||||
switch (rules.CustomCalculateMark) {
|
||||
case 1:
|
||||
num += parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 2:
|
||||
num -= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 3:
|
||||
num *= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 4:
|
||||
if (parseFloat(this.questionForm[o.TableQuestionId]) === 0) {
|
||||
num = 0
|
||||
} else {
|
||||
num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
|
||||
if (rules.ValueType === 2) {
|
||||
num = num * 100
|
||||
}
|
||||
return num.toFixed(digitPlaces)
|
||||
},
|
||||
formItemNumberChange(questionId, isTable) {
|
||||
if (isTable) {
|
||||
this.CalculationList.forEach((v, i) => {
|
||||
var find = v.CalculateQuestionList.filter(o => {
|
||||
return o.QuestionId === questionId
|
||||
})
|
||||
// find的自动计算值number
|
||||
if (find) {
|
||||
var num = this.logic(v)
|
||||
if (num !== false) {
|
||||
this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.CalculationList.forEach(v => {
|
||||
var find = v.CalculateQuestionList.filter(o => {
|
||||
return o.TableQuestionId === questionId
|
||||
})
|
||||
// find的自动计算值number
|
||||
if (find) {
|
||||
var num = this.logic(v)
|
||||
if (num !== false) {
|
||||
this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// this.$emit('formItemNumberChange')
|
||||
},
|
||||
formItemTableNumberChange() {
|
||||
this.question.TableQuestions.Questions.forEach(v => {
|
||||
if (v.Type === 'number' && v.DataSource === 1) {
|
||||
var CalculateQuestions = JSON.parse(v.CalculateQuestions)
|
||||
var num
|
||||
CalculateQuestions.forEach((o, i) => {
|
||||
if (i === 0) {
|
||||
num = this.QuestionsForm[o.TableQuestionId]
|
||||
} else {
|
||||
switch (v.CustomCalculateMark) {
|
||||
case 1:
|
||||
num += this.QuestionsForm[o.TableQuestionId]
|
||||
break;
|
||||
case 2:
|
||||
num -= this.QuestionsForm[o.TableQuestionId]
|
||||
break;
|
||||
case 3:
|
||||
num *= this.QuestionsForm[o.TableQuestionId]
|
||||
break;
|
||||
case 4:
|
||||
num /= this.QuestionsForm[o.TableQuestionId]
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$set(this.QuestionsForm, v.Id, num.toString())
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
openAddTableCol(row, index) {
|
||||
this.addOrEdit.visible = true
|
||||
this.addOrEdit.title = row.QuestionName + '表格问题'
|
||||
this.QuestionsList = row.TableQuestions.Questions
|
||||
this.AnswersList = row.TableQuestions.Answers
|
||||
if (!index && index !== 0) {
|
||||
this.addOrEdit.type = 'add'
|
||||
this.QuestionsForm = {}
|
||||
} else {
|
||||
this.addOrEdit.type = 'edit'
|
||||
console.log(this.questionForm)
|
||||
this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index])
|
||||
}
|
||||
},
|
||||
getOrganInfoList() {
|
||||
var param = {
|
||||
trialId: this.$route.query.trialId,
|
||||
lesionType: this.question.LesionType,
|
||||
// systemCriterionId: this.criterionId,
|
||||
isEnable: true
|
||||
}
|
||||
getTrialOrganList(param).then(res => {
|
||||
this.organList = res.Result
|
||||
})
|
||||
},
|
||||
formNumberItemChange(v) {
|
||||
this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||
},
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
}
|
||||
if (question.TableQuestionType === 1 && question.RelationQuestions.length > 0) {
|
||||
var index = this.organList.findIndex(item => item[question.DataTableColumn] === v)
|
||||
if (index < 0) return
|
||||
var selected = this.organList[index]
|
||||
this.question.RelationQuestions.map(qs => {
|
||||
var val = selected[qs.DataTableColumn]
|
||||
// if (typeof val === 'boolean') {
|
||||
// // val = String(val)
|
||||
// }
|
||||
this.$emit('setFormItemData', { key: qs.Id, val: val })
|
||||
})
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
uploadScreenshot(param) {
|
||||
if (!this.visitTaskId) return
|
||||
const loading = this.$loading({
|
||||
target: document.querySelector('.ecrf-wrapper'),
|
||||
fullscreen: false,
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
spinner: 'el-icon-loading'
|
||||
})
|
||||
const formData = new FormData()
|
||||
formData.append('file', param.file)
|
||||
uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
this.fileList.push({ url: `/api/${res.Result.Path}` })
|
||||
this.urls.push(res.Result.Path)
|
||||
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
|
||||
}
|
||||
loading.close()
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
handleBeforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
// this.fileList = []
|
||||
return true
|
||||
} else {
|
||||
this.$alert(`必须是 ${this.accept} 格式`)
|
||||
return false
|
||||
}
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var index = fileName.lastIndexOf('.')
|
||||
var suffix = fileName.substring(index + 1, fileName.length)
|
||||
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
// 预览图片
|
||||
handlePictureCardPreview(file) {
|
||||
this.imageUrl = file.url
|
||||
this.imgVisible = true
|
||||
},
|
||||
// 删除图片
|
||||
handleRemove(file, fileList) {
|
||||
this.imageUrl = ''
|
||||
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
|
||||
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
|
||||
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.my_dialog{
|
||||
.criterion-form-item{
|
||||
width: 100%;
|
||||
>>>.el-form-item__content{
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.criterion-form-item{
|
||||
>>>.criterion-form-item .el-form-item{
|
||||
display: block;
|
||||
.el-form-item__label{
|
||||
display: block;
|
||||
color: #c8c8c8;
|
||||
float: none;
|
||||
text-align: left;
|
||||
}
|
||||
.el-input--small .el-input__inner{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.el-form-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
>>>.el-form-item__content{
|
||||
}
|
||||
.el-input{
|
||||
width:100%;
|
||||
}
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
>>>.el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
>>>.el-table__body-wrapper::-webkit-scrollbar{
|
||||
height: 10px!important;
|
||||
}
|
||||
>>>.el-table__fixed-right::before{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,162 @@
|
|||
<template>
|
||||
<div style="display: flex;justify-content: center">
|
||||
<div style="width: 600px;text-align: center;border: 1px solid #e6e6e6;margin-top:40px;padding:10px;">
|
||||
<div class="trial-myinfo-head" style="font-size: 30px;line-height: 120px;">
|
||||
<!-- 首次登录修改密码 -->
|
||||
{{ $t('recompose:title:init') }}
|
||||
</div>
|
||||
<el-form ref="passwordForm" v-loading="loading" label-position="right" :model="password" :rules="passwordFormRules" label-width="120px">
|
||||
<!-- 用户名 -->
|
||||
<el-form-item :label="$t('recompose:form:userName')" prop="NewUserName">
|
||||
<el-input v-model="password.NewUserName" />
|
||||
</el-form-item>
|
||||
<!-- 旧密码 -->
|
||||
<el-form-item :label="$t('recompose:form:oldPassword')" prop="OldPassWord">
|
||||
<el-input v-model="password.OldPassWord" type="password" show-password auto-complete="new-password" />
|
||||
</el-form-item>
|
||||
<!-- 新密码 -->
|
||||
<el-form-item :label="$t('recompose:form:newPassword')" prop="NewPassWord">
|
||||
<el-input v-model="password.NewPassWord" type="password" show-password auto-complete="new-password" />
|
||||
</el-form-item>
|
||||
<!-- 确认密码 -->
|
||||
<el-form-item :label="$t('recompose:form:confirmPassword')" prop="ConfirmPassWord">
|
||||
<el-input v-model="password.ConfirmPassWord" type="password" show-password auto-complete="new-password" />
|
||||
</el-form-item>
|
||||
<el-form-item style="text-align:right">
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
size="small"
|
||||
@click="cancel"
|
||||
>
|
||||
{{ $t('recompose:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="save"
|
||||
>
|
||||
{{ $t('recompose:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { modifyPassword } from '@/api/admin.js'
|
||||
import md5 from 'js-md5'
|
||||
import {mapMutations} from "vuex";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
password: {
|
||||
NewUserName: null
|
||||
},
|
||||
passwordFormRules: {
|
||||
NewUserName: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
OldPassWord: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
NewPassWord: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
validator: this.$validatePassword
|
||||
},
|
||||
],
|
||||
ConfirmPassWord: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
]
|
||||
},
|
||||
userId: null,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$set(this.password, 'NewUserName', this.$route.query.userName)
|
||||
if (!this.password.NewUserName) {
|
||||
// 该页面只提供给首次进入系统的用户使用
|
||||
this.$alert(this.$t('recompose:message:warning'))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
||||
async logout() {
|
||||
var loginType = zzSessionStorage.getItem('loginType')
|
||||
await this.$store.dispatch('user/logout')
|
||||
if (loginType) {
|
||||
this.$router.push(`/login?loginType=${loginType}`)
|
||||
} else {
|
||||
this.$router.push(`/login`)
|
||||
}
|
||||
this.$i18n.locale = 'zh'
|
||||
this.setLanguage('zh')
|
||||
this.$updateDictionary()
|
||||
},
|
||||
save() {
|
||||
this.$refs.passwordForm.validate(valid => {
|
||||
if (valid) {
|
||||
if (this.password.NewPassWord !== this.password.ConfirmPassWord) {
|
||||
// 两次密码输入不一致
|
||||
this.$alert(this.$t('recompose:message:passwordDiffer'))
|
||||
return
|
||||
}
|
||||
const param = {
|
||||
NewUserName: this.password.NewUserName,
|
||||
NewPassWord: md5(this.password.NewPassWord),
|
||||
OldPassWord: md5(this.password.OldPassWord)
|
||||
}
|
||||
this.loading = true
|
||||
modifyPassword(param).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(this.$t('recompose:message:updatedSuccessfully'))
|
||||
setTimeout(() => {
|
||||
this.logout()
|
||||
}, 500)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
}
|
||||
})
|
||||
},
|
||||
cancel() {
|
||||
this.$refs['passwordForm'].resetFields()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.reset-wrapper {
|
||||
padding: 20px;
|
||||
}
|
||||
.reset-wrapper .el-page-header {
|
||||
line-height: 50px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.reset-wrapper .box-wrapper {
|
||||
width: 60%;
|
||||
margin: 20px auto;
|
||||
padding: 10px;
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
>>>.is-error{
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
input:-webkit-autofill {
|
||||
-webkit-text-fill-color: #ededed !important;
|
||||
box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||
background-color:transparent;
|
||||
background-image: none;
|
||||
transition: background-color 50000s ease-in-out 0s;
|
||||
}
|
||||
input {
|
||||
background-color:transparent;
|
||||
caret-color: #fff;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="sysTemplateFrom"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
label-width="90px"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
class="upload-temporary-file"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="Code" prop="Code">
|
||||
<el-input v-model="form.Code" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务场景: " prop="BusinessScenarioEnum">
|
||||
<el-select
|
||||
v-model="form.BusinessScenarioEnum"
|
||||
style="width:100%;"
|
||||
size="small"
|
||||
filterable
|
||||
disabled
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Common_File_BusinessScenario"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文件: ">
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
accept=".xls,.xlsx,.doc,.docx"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemoveFile"
|
||||
:show-file-list="true"
|
||||
:file-list="fileList"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum">Select</el-button>
|
||||
<span
|
||||
slot="tip"
|
||||
style="margin-left:10px;"
|
||||
class="el-upload__tip"
|
||||
>
|
||||
(must be in xlsx/xls/doc/docx format)
|
||||
</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件名" prop="Name">
|
||||
<el-input v-model="form.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="阅片标准: " prop="CriterionTypeEnum">
|
||||
<el-select
|
||||
v-model="form.CriterionTypeEnum"
|
||||
style="width:100%;"
|
||||
size="small"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.CriterionType"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
||||
<el-radio-group v-model="form.IsDeleted">
|
||||
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input
|
||||
v-model="form.Description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
placeholder="请输入内容"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum" @click="handleSave">Save</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateCommonDocument, uploadCommonDoc } from '@/api/dictionary'
|
||||
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
|
||||
export default {
|
||||
name: 'TemplateForm',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
},
|
||||
isDistinguishCriteria: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
Id: '',
|
||||
Code: '',
|
||||
FileTypeEnum: null,
|
||||
BusinessScenarioEnum: null,
|
||||
CriterionTypeEnum: null,
|
||||
Name: '',
|
||||
Path: '',
|
||||
Description: '',
|
||||
IsDeleted: false
|
||||
},
|
||||
rules: {
|
||||
Code: [{ required: true, message: 'Please specify', trigger: ['blur'] }],
|
||||
Name: [{ required: true, message: 'Please specify', trigger: ['blur'] }],
|
||||
CriterionTypeEnum: [{ required: this.isDistinguishCriteria, message: 'Please select', trigger: ['blur'] }],
|
||||
BusinessScenarioEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }]
|
||||
},
|
||||
fileList: [],
|
||||
loading: false,
|
||||
dictionaryList: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getDicData()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
if (this.data.Path) {
|
||||
this.fileList = [
|
||||
{
|
||||
name: this.data.Name,
|
||||
path: this.data.Path,
|
||||
type: this.data.Type
|
||||
}
|
||||
]
|
||||
}
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取文件类型下拉框
|
||||
getDicData() {
|
||||
this.loading = true
|
||||
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type']).then(res => {
|
||||
this.dictionaryList = { ...res.Result }
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
this.fileList = []
|
||||
return true
|
||||
} else {
|
||||
this.$alert('必须是word/excel格式')
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
handleUploadFile(param) {
|
||||
this.loading = true
|
||||
uploadCommonDoc(param.file).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.form.Path = res.Result.FilePath
|
||||
this.form.Name = param.file.name
|
||||
const file = { name: this.form.Name, path: this.form.Path }
|
||||
this.fileList.push(file)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs.sysTemplateFrom.validate(valid => {
|
||||
if (!valid) return
|
||||
if (!this.form.Name) {
|
||||
this.$alert('Please select file.')
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
addOrUpdateCommonDocument(this.form).then(res => {
|
||||
this.loading = false
|
||||
this.$emit('closeDialog')
|
||||
this.$emit('getList')
|
||||
this.$message.success('保存成功!')
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleRemoveFile() {
|
||||
this.fileList = []
|
||||
this.form.Path = ''
|
||||
this.form.Name = ''
|
||||
},
|
||||
handlePreview(file) {
|
||||
if (file.fullPath) {
|
||||
window.open(file.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(`Upload is currently limited to 1 file`)
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var typeArr = ['xls', 'xlsx', 'doc', 'docx']
|
||||
var extendName = fileName.substring(fileName.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) !== -1) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-temporary-file{
|
||||
.upload-container .el-upload--text {
|
||||
border: none;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
.upload-container .el-input--small {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-container .el-icon-circle-check {
|
||||
color: #428bca;
|
||||
font-size: 13px;
|
||||
}
|
||||
.account_item_clear{
|
||||
.el-tag__close{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,499 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item label="受试者编号">
|
||||
<el-input
|
||||
v-model="searchData.SubjectCode"
|
||||
style="width:130px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务状态">
|
||||
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskState" :key="'TaskState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务类型">
|
||||
<el-select v-model="searchData.ReadingCategory" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ReadingCategory" :key="'ReadingCategory' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column type="index" width="40" align="left" />
|
||||
<!-- 是否加急 -->
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
min-width="100"
|
||||
label="是否加急"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 任务编号 -->
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
min-width="100"
|
||||
label="任务编号"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 受试者编号 -->
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
min-width="100"
|
||||
label="受试者编号"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 盲态访视名称 -->
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
min-width="100"
|
||||
label="盲态访视名称"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
min-width="100"
|
||||
label="任务类型"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片状态 -->
|
||||
<!-- <el-table-column
|
||||
prop="TaskAllocationState"
|
||||
min-width="100"
|
||||
label="阅片状态"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingTaskState === 2" type="primary">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- 分配时间 -->
|
||||
<el-table-column
|
||||
prop="AllocateTime"
|
||||
min-width="100"
|
||||
label="分配时间"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 签名时间 -->
|
||||
<el-table-column
|
||||
prop="SignTime"
|
||||
min-width="100"
|
||||
label="签名时间"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReReadingApplyState"
|
||||
label="申请状态"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 4 || scope.row.ReReadingApplyState === 5" type="danger">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 2" type="primary">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 3" type="warning">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="250"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 查看 -->
|
||||
<el-button
|
||||
circle
|
||||
title="查看"
|
||||
icon="el-icon-view"
|
||||
@click="handleReadImage(scope.row)"
|
||||
/>
|
||||
<!-- 申请重阅 -->
|
||||
<el-button
|
||||
:disabled="scope.row.TaskState !== 0 || scope.row.ReadingTaskState !== 2 || scope.row.ReReadingApplyState === 2 || scope.row.ReReadingApplyState === 4 || scope.row.ReReadingApplyState === 5"
|
||||
icon="el-icon-collection"
|
||||
circle
|
||||
title="申请重阅"
|
||||
@click="openApplyReReading(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="!scope.row.ReReadingApplyState"
|
||||
icon="el-icon-toilet-paper"
|
||||
circle
|
||||
title="退回重阅历史"
|
||||
@click="reReadingHistory(scope.row, 1)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</template>
|
||||
<el-dialog
|
||||
v-if="ApplyforReasonVisible"
|
||||
title="申请重阅"
|
||||
:visible.sync="ApplyforReasonVisible"
|
||||
width="1460px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-form
|
||||
ref="reasonForm"
|
||||
:rules="rules"
|
||||
:model="ApplyforReasonForm"
|
||||
class="demo-ruleForm"
|
||||
size="small"
|
||||
label-width="150px"
|
||||
>
|
||||
<el-divider content-position="left">申请原因</el-divider>
|
||||
<el-form-item
|
||||
label="申请原因"
|
||||
prop="Type"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select')},
|
||||
]"
|
||||
>
|
||||
<el-radio-group v-model="ApplyforReasonForm.Type">
|
||||
<!-- 问题已解决 -->
|
||||
<el-radio :label="1">阅片记录错误</el-radio>
|
||||
<!-- 问题无法解决强制关闭质疑 -->
|
||||
<el-radio :label="2">其他</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 原因 -->
|
||||
<el-form-item v-if="ApplyforReasonForm.Type === 2" label="备注" prop="RequestReReadingReason">
|
||||
<el-input
|
||||
v-model="ApplyforReasonForm.RequestReReadingReason"
|
||||
type="textarea"
|
||||
style="width: 400px"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:placeholder="$t('common:ruleMessage:specify')"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="是否复制阅片表单"
|
||||
prop="IsCopyOrigenalForms"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select')},
|
||||
]"
|
||||
>
|
||||
<el-radio-group v-model="ApplyforReasonForm.IsCopyOrigenalForms">
|
||||
<!-- 问题已解决 -->
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<!-- 问题无法解决强制关闭质疑 -->
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="ApplyforReasonForm.IsCopyOrigenalForms"
|
||||
label="是否复制后续表单"
|
||||
prop="IsCopyFollowForms"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select')},
|
||||
]"
|
||||
>
|
||||
<el-radio-group v-model="ApplyforReasonForm.IsCopyFollowForms">
|
||||
<!-- 问题已解决 -->
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<!-- 问题无法解决强制关闭质疑 -->
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-divider content-position="left">影响的任务列表</el-divider>
|
||||
<div style="padding:10px;border: 1px solid #e0e0e0;max-height:650px;overflow-y: auto;">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="InfluenceTaskList"
|
||||
stripe
|
||||
height="100"
|
||||
style="min-height: 400px;"
|
||||
>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="任务编号"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
label="中心编号"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="受试者编号"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
min-width="100"
|
||||
label="任务类型"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ReadingTaskState"
|
||||
label="阅片状态"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingTaskState === 2" type="primary">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="OptType"
|
||||
label="生效后影响"
|
||||
min-width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.OptType === 0" type="primary">{{ $fd('ReReadingOrBackOptType', scope.row.OptType) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OptType === 1" type="danger">{{ $fd('ReReadingOrBackOptType', scope.row.OptType) }}</el-tag>
|
||||
<el-tag v-if="scope.row.OptType === 2" type="warning">{{ $fd('ReReadingOrBackOptType', scope.row.OptType) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片人"
|
||||
min-width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template v-if="scope.row.DoctorUser" slot-scope="scope">
|
||||
{{ scope.row.DoctorUser.UserName }}({{ scope.row.DoctorUser.FullName }})
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ApplyforReasonVisible = false;ApplyforReasonForm = { Type: null, RequestReReadingReason: null }">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="applyReReading">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getIRHaveReadTaskList } from '@/api/trials'
|
||||
import { applyReReading, getReReadingOrBackInfluenceTaskList } from '@/api/trials/reading'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getToken } from '@/utils/auth'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
SubjectCode: '',
|
||||
SortField: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
TaskState: null,
|
||||
ReadingCategory: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'ReadTask',
|
||||
components: { BaseContainer, Pagination },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
trialId: '',
|
||||
ApplyforReasonVisible: false,
|
||||
ApplyforReasonForm: {
|
||||
Type: null,
|
||||
RequestReReadingReason: null,
|
||||
IsCopyOrigenalForms: null,
|
||||
IsCopyFollowForms: null
|
||||
},
|
||||
InfluenceTaskList: [],
|
||||
rules: {
|
||||
Type: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
IsCopyOrigenalForms: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
RequestReReadingReason: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 重阅历史
|
||||
reReadingHistory(row) {
|
||||
this.$router.push({ path: `/trials/trials-panel/reading/rereadTask?trialId=${this.$route.query.trialId}&trialCode=${this.$route.query.trialCode}&researchProgramNo=${this.$route.query.researchProgramNo}&SiteId=${row.SiteId}&SubjectCode=${row.SubjectCode}&TaskName=${row.TaskName}` })
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
getIRHaveReadTaskList(this.searchData).then(res => {
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
handleReadImage(row) {
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/noneDicomReading?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
openApplyReReading(row) {
|
||||
this.rowData = { ...row }
|
||||
this.loading = true
|
||||
getReReadingOrBackInfluenceTaskList(row.Id, true).then(res => {
|
||||
this.InfluenceTaskList = res.Result
|
||||
this.ApplyforReasonVisible = true
|
||||
this.ApplyforReasonForm = {
|
||||
Type: null,
|
||||
Remake: null
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
// 申请重阅
|
||||
applyReReading() {
|
||||
this.$refs.reasonForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
TaskIdList: [
|
||||
this.rowData.Id
|
||||
],
|
||||
TrialId: this.$route.query.trialId,
|
||||
IsCopyOrigenalForms: this.ApplyforReasonForm.IsCopyOrigenalForms,
|
||||
IsCopyFollowForms: this.ApplyforReasonForm.IsCopyFollowForms,
|
||||
RequestReReadingType: 1,
|
||||
RequestReReadingReason: this.ApplyforReasonForm.Type === 2 ? this.ApplyforReasonForm.RequestReReadingReason : '阅片记录错误'
|
||||
}
|
||||
applyReReading(params).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('申请重阅成功')
|
||||
this.getList()
|
||||
this.ApplyforReasonVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,427 @@
|
|||
<template>
|
||||
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="globalForm.taskList"
|
||||
>
|
||||
<!-- 访视名称 -->
|
||||
<el-table-column
|
||||
prop="BlindName"
|
||||
:label="$t('trials:globalReview:table:visitName')"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
/>
|
||||
<!-- 评估结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:evaluationRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.evaluationQsList"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否同意访视结果 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:globalReview:table:isAgreeEvaluationRes')"
|
||||
show-overflow-tooltip
|
||||
width="170"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="readingTaskState<2 ">
|
||||
<el-form-item
|
||||
:prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['change','blur']},
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
|
||||
@change="handleAgreeOrNotChange(scope.$index,scope.row.AgreeOrNot[0].GlobalAnswerType)"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingYesOrNo"
|
||||
:key="'AgreeOrNot' + item.value"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1" type="primary">
|
||||
{{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0" type="danger"> {{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
|
||||
<span v-else />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 调整后结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:adjustedRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.adjustedQsList"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs"
|
||||
show-overflow-tooltip
|
||||
:min-width="index === 3 ? '200' : '200'"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="readingTaskState<2 ">
|
||||
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
|
||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
|
||||
</span>
|
||||
<el-form-item
|
||||
v-else
|
||||
style="margin-bottom: 0;"
|
||||
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required:parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
|
||||
]"
|
||||
>
|
||||
<label v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
|
||||
<!-- 裁判问题 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0 ">
|
||||
<el-tooltip class="item" effect="dark" v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||
<el-option
|
||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
style="width:90%;"
|
||||
v-else
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||
<el-option
|
||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
<!-- 评估更新类型 GlobalAnswerType:3 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
<el-tooltip class="item" effect="dark" v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in globalInfo.assessTypeList"
|
||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && !val.IsBaseLineUse)"
|
||||
:key="val.Code"
|
||||
:label="language === 'en'?val.Value:val.ValueCN"
|
||||
:value="val.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in globalInfo.assessTypeList"
|
||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && !val.IsBaseLineUse)"
|
||||
:key="val.Code"
|
||||
:label="language === 'en'?val.Value:val.ValueCN"
|
||||
:value="val.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<el-input
|
||||
v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
type="textarea"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
style="width:90%;"
|
||||
:autosize="{ minRows: 2 }"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer">
|
||||
|
||||
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
|
||||
</span>
|
||||
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode,parseInt(scope.row.AfterQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:globalReview:table:view')"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { batchSubmitGlobalReadingInfo } from '@/api/trials'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
props: {
|
||||
globalInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
globalForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
assessTypes: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
|
||||
},
|
||||
methods: {
|
||||
getText(val, row, type) {
|
||||
var text
|
||||
if (type === 3) {
|
||||
var o = this.globalInfo.assessTypeList.find(v => {
|
||||
return parseInt(v.Code) === parseInt(val)
|
||||
})
|
||||
if (!o) {
|
||||
return ''
|
||||
}
|
||||
return this.language === 'en' ? o.Value : o.ValueCN
|
||||
} else if (row.TypeValue) {
|
||||
return val
|
||||
} else if (row.DictionaryCode) {
|
||||
return this.$fd(row.DictionaryCode, parseInt(val))
|
||||
}
|
||||
},
|
||||
handleView(row) {
|
||||
var token = getToken()
|
||||
var visitTaskId = row.VisitTaskId
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
path = `/readingDicoms?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
}
|
||||
const routeData = this.$router.resolve({ path })
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$refs['globalRuleForm'].validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
var answerList = []
|
||||
item.AfterQuestionList.map(i => {
|
||||
var obj = {}
|
||||
if (i.QuestionId) {
|
||||
obj.questionId = i.QuestionId
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.QuestionId}`]
|
||||
} else {
|
||||
obj.questionId = ''
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.GlobalAnswerType}`]
|
||||
}
|
||||
answerList.push(obj)
|
||||
})
|
||||
answerList.push({ questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
|
||||
answer: this.globalForm[ `${index}${item.AgreeOrNot[0].GlobalAnswerType}`] })
|
||||
|
||||
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
|
||||
})
|
||||
var params = {
|
||||
globalTaskId: this.globalInfo.visitTaskId,
|
||||
subjectId: this.globalInfo.subjectId,
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
batchSubmitGlobalReadingInfo(params).then(res => {
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
getBeforeAnswer(qsId, row) {
|
||||
var i = row.BeforeQuestionList.findIndex(item => item.QuestionName === qsId)
|
||||
|
||||
if (i > -1 && row.BeforeQuestionList[i].Answer) {
|
||||
var answer = ''
|
||||
if (row.BeforeQuestionList[i].DictionaryCode) {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
} else {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
}
|
||||
return answer
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
handleAgreeOrNotChange(index, globalAnswerType) {
|
||||
var agreeOrNot = parseInt(this.globalForm[`${index}${globalAnswerType}`])
|
||||
if (agreeOrNot === 1) {
|
||||
var qsList = this.globalForm.taskList[index].AfterQuestionList
|
||||
qsList.map(v => {
|
||||
if (v.QuestionId) {
|
||||
this.globalForm[`${index}${v.QuestionId}`] = ''
|
||||
} else if (v.GlobalAnswerType !== globalAnswerType) {
|
||||
this.globalForm[`${index}${v.GlobalAnswerType}`] = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getAssessType(v) {
|
||||
console.log(this.language)
|
||||
var i = this.globalInfo.assessTypeList.findIndex(i => String(i.Code) === String(v))
|
||||
if (i > -1) {
|
||||
return this.language === 'en' ? this.globalInfo.assessTypeList[i].Value : this.globalInfo.assessTypeList[i].ValueCN
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
>>>.el-form-item label:before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
>>>.el-textarea .el-input__count{
|
||||
background: rgba(0,0,0,0);
|
||||
line-height: normal;
|
||||
}
|
||||
>>>.el-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,439 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<el-tabs v-model="TrialReadingCriterionId" type="border-card">
|
||||
<el-tab-pane v-for="i of trialCriterionList" :key="i.TrialReadingCriterionId" :label="i.TrialReadingCriterionName" :name="i.TrialReadingCriterionId">
|
||||
<div v-if="TrialReadingCriterionId === i.TrialReadingCriterionId">
|
||||
<div slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<!-- 是否加急 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:isUrgent')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.IsUrgent"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="'IsUrgent' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:medicalFeedback:table:subjectCode')">
|
||||
<el-input
|
||||
v-model="searchData.SubjectCode"
|
||||
style="width:130px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 盲态任务标识 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:taskBlindName')"
|
||||
>
|
||||
<el-input
|
||||
v-model="searchData.TaskBlindName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 任务类型 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:readingCategory')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.ReadingCategory"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.ReadingCategory"
|
||||
:key="'ReadingCategory' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 审核状态 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:auditState')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.AuditState"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.MedicalReviewAuditState"
|
||||
:key="'AuditState' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 医学审核建议 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:auditAdvice')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.AuditAdviceEnum"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.AuditAdvice"
|
||||
:key="'AuditAdvice' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 是否认可 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
:label="$t('trials:medicalFeedback:table:doctorUserIdea')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.DoctorUserIdeaEnum"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.MedicalReviewDoctorUserIdea"
|
||||
:key="'MedicalReviewDoctorUserIdea' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:75}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
>
|
||||
<el-table-column type="index" width="40" align="left" />
|
||||
<!-- 是否加急 -->
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
min-width="100"
|
||||
:label="$t('trials:medicalFeedback:table:isUrgent')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 受试者编号 -->
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
min-width="100"
|
||||
:label="$t('trials:medicalFeedback:table:subjectCode')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
|
||||
<!-- 盲态任务标识 -->
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
min-width="100"
|
||||
:label="$t('trials:medicalFeedback:table:taskBlindName')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 阅片标准 -->
|
||||
<el-table-column
|
||||
prop="TrialReadingCriterionName"
|
||||
:label="$t('trials:medicalFeedback:table:criterionName')"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
:label="$t('trials:medicalFeedback:table:readingCategory')"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片任务状态 -->
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
:label="$t('trials:medicalFeedback:table:taskState')"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 审核状态 -->
|
||||
<el-table-column
|
||||
prop="AuditState"
|
||||
:label="$t('trials:medicalFeedback:table:auditState')"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.AuditState === 0" type="warning">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.AuditState === 1" type="primary">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.AuditState === 2" type="danger">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 首次质询时间 -->
|
||||
<el-table-column
|
||||
prop="FirstReplyTime"
|
||||
min-width="100"
|
||||
:label="$t('trials:medicalFeedback:table:firstReplyTime')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 最近回复时间 -->
|
||||
<el-table-column
|
||||
prop="LastReplyTime"
|
||||
min-width="100"
|
||||
:label="$t('trials:medicalFeedback:table:lastReplyTime')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 医学审核建议 -->
|
||||
<el-table-column
|
||||
prop="AuditAdviceEnum"
|
||||
:label="$t('trials:medicalFeedback:table:auditAdvice')"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('AuditAdvice',scope.row.AuditAdviceEnum) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否认可 -->
|
||||
<el-table-column
|
||||
prop="DoctorUserIdeaEnum"
|
||||
min-width="120"
|
||||
:label="$t('trials:medicalFeedback:table:doctorUserIdea')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('MedicalReviewDoctorUserIdea',scope.row.DoctorUserIdeaEnum) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="200"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 查看 -->
|
||||
<el-button
|
||||
:disabled="!scope.row.IsHaveQuestion || scope.row.IsInvalid"
|
||||
circle
|
||||
:title="$t('trials:medicalFeedback:table:view')"
|
||||
icon="el-icon-edit-outline"
|
||||
@click="handleReadMecialAudit(scope.row)"
|
||||
/>
|
||||
<!-- 回复 -->
|
||||
<el-button
|
||||
:disabled="!scope.row.IsHaveQuestion || scope.row.IsInvalid"
|
||||
circle
|
||||
:title="$t('trials:medicalFeedback:table:reply')"
|
||||
icon="el-icon-chat-dot-round"
|
||||
@click="handleReply(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-dialog
|
||||
v-if="chatForm.visible"
|
||||
:visible.sync="chatForm.visible"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="chatForm.title"
|
||||
width="600px"
|
||||
>
|
||||
<ChatForm
|
||||
:task-medical-review-id="currentRow.Id"
|
||||
:visit-task-id="currentRow.VisitTaskId"
|
||||
@getList="getList"
|
||||
@close="chatForm.visible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 医学审核详情 -->
|
||||
<el-dialog
|
||||
v-if="auditVisible"
|
||||
:visible.sync="auditVisible"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="true"
|
||||
:title="$t('trials:medicalFeedback:title:mfDetail')"
|
||||
>
|
||||
<MedicalAudit
|
||||
:task-medical-review-id="currentRow.Id"
|
||||
:visit-task-id="currentRow.VisitTaskId"
|
||||
:row-data="currentRow"
|
||||
@getList="getList"
|
||||
@close="auditVisible=false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getIRMedicalFeedbackList } from '@/api/trials'
|
||||
import { getTrialCriterionList } from '@/api/trials/reading'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import ChatForm from './components/ChatForm'
|
||||
import MedicalAudit from '@/views/trials/trials-panel/reading/mim-medical-audit/components/MedicalAudit'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
IsUrgent: null,
|
||||
SubjectCode: '',
|
||||
TaskBlindName: '',
|
||||
ReadingCategory: null,
|
||||
AuditState: null,
|
||||
AuditAdviceEnum: null,
|
||||
DoctorUserIdeaEnum: null,
|
||||
PageIndex: 1,
|
||||
PageSize: 20
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'ReadTask',
|
||||
components: { BaseContainer, Pagination, ChatForm, MedicalAudit },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
trialId: '',
|
||||
currentRow: {},
|
||||
chatForm: { visible: false, title: '' }, // 质询记录
|
||||
auditVisible: false,
|
||||
trialCriterionList: [],
|
||||
TrialReadingCriterionId: '0'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
TrialReadingCriterionId(v) {
|
||||
if (v) {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getTrialCriterionList()
|
||||
},
|
||||
methods: {
|
||||
getTrialCriterionList() {
|
||||
getTrialCriterionList(this.trialId).then(res => {
|
||||
this.trialCriterionList = res.Result
|
||||
this.TrialReadingCriterionId = this.trialCriterionList[0].TrialReadingCriterionId
|
||||
}).catch(() => {})
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId
|
||||
getIRMedicalFeedbackList(this.searchData).then(res => {
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
handleReadMecialAudit(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.auditVisible = true
|
||||
},
|
||||
handleReply(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.chatForm.title = `${this.$t('trials:medicalFeedback:title:qaRecord')} (${row.SubjectCode} ${row.TaskBlindName})`
|
||||
this.chatForm.visible = true
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
functional: true,
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
render(h, context) {
|
||||
const { icon, title } = context.props
|
||||
const vnodes = []
|
||||
|
||||
if (icon) {
|
||||
vnodes.push(<svg-icon icon-class={icon}/>)
|
||||
}
|
||||
|
||||
if (title) {
|
||||
vnodes.push(<span slot='title'>{(title)}</span>)
|
||||
}
|
||||
return vnodes
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,201 @@
|
|||
<template>
|
||||
<div class="trialsTab">
|
||||
<el-tabs v-model="trialsTab" @tab-click="clickTab">
|
||||
<el-tab-pane v-for="item of trialsRouter.children.find(v => {return v.name == 'TrialsPanel'}).children" :key="`tab${item.path}`" :disabled="TotalNeedSignTrialDocCount !== 0" :label="$t(item.LanguageMark)" :name="item.path">
|
||||
<el-tabs v-if="!item.tabHiddn" v-model="trialsTabChild" @tab-click="clickTab">
|
||||
<el-tab-pane
|
||||
v-for="item1 of item.children"
|
||||
:key="`tab1${item1.path}`"
|
||||
:disabled="TotalNeedSignTrialDocCount !== 0 || (TrialStatusStr === 'Initializing' && (item1.path === '/trials/trials-panel/setting/personnel-manage' || item1.path === '/trials/trials-panel/setting/qc-question'))"
|
||||
:label="$t(item1.LanguageMark)"
|
||||
:name="item1.path"
|
||||
/>
|
||||
</el-tabs>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div style="position: absolute;top: 0;right: 0;display: flex;justify-content: space-between;align-items: center">
|
||||
<trials-select />
|
||||
<div>
|
||||
<i class="iconfont" style="font-size: 30px;color:#ccc"></i>
|
||||
</div>
|
||||
<div class="my_icon_box" title="返回项目列表" @click="goBack">
|
||||
<i class="iconfont"></i>
|
||||
<span>返回</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { getTrialSelect } from '@/api/trials'
|
||||
import TrialsSelect from '@/components/TrialsSelect/index.vue'
|
||||
import { getUserDocumentList } from '@/api/trials'
|
||||
import store from '@/store'
|
||||
export default {
|
||||
name: 'TrialsTab',
|
||||
components: {
|
||||
TrialsSelect
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
trialsRouter: this.$store.getters.routes.find(v => { return v.name === 'Trials' }),
|
||||
trialsTab: null,
|
||||
trialsTabChild: null,
|
||||
tabTrialsId: null,
|
||||
options: [],
|
||||
TrialStatusStr: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['TotalNeedSignTrialDocCount'])
|
||||
},
|
||||
watch: {
|
||||
$route(v, ov) {
|
||||
this.selectedTab()
|
||||
var query = ``
|
||||
var url = window.location.href
|
||||
if (~url.indexOf('?')) {
|
||||
query = url.split('?')[1]
|
||||
}
|
||||
zzSessionStorage.setItem('lastWorkbench', `${v.path}${query ? '?' : ''}${query}`)
|
||||
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
||||
if (this.trialsTab === '/trials/trials-panel') {
|
||||
this.$router.replace({ path: `${firstGoIn.path}${query ? '?' : ''}${query}` })
|
||||
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
||||
this.$router.replace({ path: `${firstGoIn.children[0].path}${query ? '?' : ''}${query}` })
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var query = ``
|
||||
var url = window.location.href
|
||||
if (~url.indexOf('?')) {
|
||||
query = url.split('?')[1]
|
||||
}
|
||||
getUserDocumentList({ TrialId: this.$route.query.trialId }).then(async res => {
|
||||
var total = res.OtherInfo.NeedSignCount
|
||||
var TrialStatusStr = res.OtherInfo.TrialStatusStr
|
||||
this.TrialStatusStr = TrialStatusStr
|
||||
await store.dispatch('user/setTotalNeedSignTrialDocCount', total)
|
||||
await store.dispatch('user/setTrialStatusStr', TrialStatusStr)
|
||||
}).catch(() => {
|
||||
})
|
||||
this.selectedTab()
|
||||
this.getTrialList()
|
||||
var firstGoIn = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children[0]
|
||||
if (this.trialsTab === '/trials/trials-panel') {
|
||||
this.$router.replace({ path: `${firstGoIn.path}${query ? '?' : ''}${query}` })
|
||||
if (firstGoIn.children && firstGoIn.children.length > 0) {
|
||||
this.$router.replace({ path: `${firstGoIn.children[0].path}${query ? '?' : ''}${query}` })
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.push({ path: '/trials/trials-list' })
|
||||
},
|
||||
selectTrials(v) {
|
||||
var trial = this.options.find(o => {
|
||||
return o.Id === v
|
||||
})
|
||||
this.$router.push({ path: `/trials/trials-panel?trialId=${trial.Id}&trialCode=${trial.TrialCode}` })
|
||||
},
|
||||
getTrialList() {
|
||||
getTrialSelect()
|
||||
.then(res => {
|
||||
this.options = res.Result
|
||||
this.tabTrialsId = this.$route.query.trialId
|
||||
})
|
||||
.catch(() => {
|
||||
})
|
||||
},
|
||||
selectedTab() {
|
||||
var path = this.$route.path
|
||||
if (this.$route.path.split('/').length > 4) {
|
||||
this.trialsTab = this.getValue(path)
|
||||
this.trialsTabChild = path
|
||||
} else {
|
||||
this.trialsTab = path
|
||||
}
|
||||
},
|
||||
getValue(url) {
|
||||
var site = url.lastIndexOf('\/')
|
||||
return url.substring(0, site)
|
||||
},
|
||||
clickTab(v) {
|
||||
try {
|
||||
var query = ``
|
||||
var url = window.location.href
|
||||
if (~url.indexOf('?')) {
|
||||
query = url.split('?')[1]
|
||||
}
|
||||
this.$router.push({ path: `${v.name}${query ? '?' : ''}${query}` })
|
||||
var trialsPanelList = this.trialsRouter.children.find(v => { return v.name === 'TrialsPanel' }).children
|
||||
var isHasChild = trialsPanelList.find(c => { return c.path === v.name }) && trialsPanelList.find(c => { return c.path === v.name }).children
|
||||
if (trialsPanelList.find(c => { return c.path === v.name }) && trialsPanelList.find(c => { return c.path === v.name }).tabHiddn) {
|
||||
return
|
||||
}
|
||||
if (isHasChild && isHasChild.length > 0) {
|
||||
this.trialsTabChild = isHasChild[0].path
|
||||
this.$router.push({ path: `${this.trialsTabChild}${query ? '?' : ''}${query}` })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.trialsTab{
|
||||
.my_icon_box{
|
||||
padding:0 20px 0 0;
|
||||
transition: color,transform .3s;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
&:hover{
|
||||
color: #00d1b2;
|
||||
}
|
||||
span{
|
||||
margin-left: 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.el-tabs__header{
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
position: relative;
|
||||
.el-input--medium .el-input__inner{
|
||||
height: 44px;line-height: 44px;width: 280px;
|
||||
border: none;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.base-model-wrapper{
|
||||
.el-dialog__header{
|
||||
padding: 10px;
|
||||
.el-dialog__headerbtn{
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
.el-dialog__body{
|
||||
padding:10px 10px 10px 10px;
|
||||
.base-modal-body{
|
||||
min-height: 100px;
|
||||
max-height:650px;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
}
|
||||
.el-dialog__footer{
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,446 @@
|
|||
<template>
|
||||
<div class="report-wrapper">
|
||||
<el-card v-loading="loading" shadow="never">
|
||||
<div slot="header" class="clearfix report-header">
|
||||
<h3 style="margin:0;padding:0;">电子影像病例报告表(eICRF)</h3>
|
||||
<div v-if="readingTaskState<2" style="margin-left:auto">
|
||||
<el-button type="primary" size="small" @click="getReportInfo">刷新</el-button>
|
||||
<el-button type="primary" size="small" @click="handleSave(true)">保存</el-button>
|
||||
<el-button type="primary" size="small" @click="handleConfirm">确认</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:5px">
|
||||
<el-table
|
||||
ref="reportList"
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="taskQuestions"
|
||||
row-key="Id"
|
||||
border
|
||||
default-expand-all
|
||||
height="100"
|
||||
:tree-props="{children: 'Childrens', hasChildren: 'hasChildren'}"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label=""
|
||||
show-overflow-tooltip
|
||||
width="350px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.QuestionName">{{ scope.row.QuestionName }}</span>
|
||||
<span
|
||||
v-else
|
||||
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
||||
>
|
||||
{{ scope.row.GroupName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="task in visitTaskList"
|
||||
:key="task.VisitTaskId"
|
||||
prop="date"
|
||||
:label="task.BlindName"
|
||||
show-overflow-tooltip
|
||||
width="200px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<template v-if="task.VisitTaskId === visitTaskId && !task.IsBaseLine && readingTaskState < 2 && scope.row.QuestionType=== 13">
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="scope.row.Type==='input'"
|
||||
v-model="scope.row.Answers[task.VisitTaskId]"
|
||||
size="mini"
|
||||
/>
|
||||
|
||||
<el-select
|
||||
v-else-if="scope.row.Type==='select' && scope.row.DictionaryCode"
|
||||
v-model="scope.row.Answers[task.VisitTaskId]"
|
||||
size="mini"
|
||||
@change="handleEvaluateResultChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>{{ scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)? scope.row.Answers[task.VisitTaskId]:'' }}</span>
|
||||
</template>
|
||||
<template v-else-if="tumorEvaluate && task.VisitTaskId === visitTaskId && readingTaskState < 2 && scope.row.QuestionType=== 14 && scope.row.Answers && currentEvaluateResult !== tumorEvaluate">
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="scope.row.Type==='input'"
|
||||
v-model="scope.row.Answers[task.VisitTaskId]"
|
||||
size="mini"
|
||||
@change="evaluateReasonChange"
|
||||
/>
|
||||
<p style="width: 180px;white-space: normal;word-break: break-all;word-wrap: break-word;">系统评估结果为:<span style="color:red">{{ $fd('OverallAssessment',tumorEvaluate) }}</span>,与当前调整的结果不一致,请填写调整原因</p>
|
||||
</template>
|
||||
|
||||
<template v-else-if="scope.row.DictionaryCode">
|
||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
||||
</template>
|
||||
|
||||
<template v-else-if="scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:parseInt(scope.row.Answers[task.VisitTaskId])>0?`${scope.row.Answers[task.VisitTaskId]}mm`:'' }}
|
||||
<!-- isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?'':`${scope.row.Answers[task.VisitTaskId]}mm` -->
|
||||
<!-- {{ scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)? scope.row.Answers[task.VisitTaskId]:'' }} -->
|
||||
</template>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions } from '@/api/trials'
|
||||
import Store from './Store'
|
||||
import const_ from '@/const/sign-code'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
name: 'ReportPage',
|
||||
components: { SignForm },
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
visitTaskList: [],
|
||||
taskQuestions: [],
|
||||
loading: false,
|
||||
answers: [],
|
||||
readingTaskState: 2,
|
||||
tumorEvaluate: '',
|
||||
currentEvaluateResult: '',
|
||||
answerArr: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
taskQuestions() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportList.doLayout()
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
Store.$on('getReportInfo', isRefresh => {
|
||||
if (!isRefresh) return
|
||||
this.getReportInfo()
|
||||
})
|
||||
this.getReportInfo()
|
||||
},
|
||||
beforeDestroy() {
|
||||
Store.$off('getReportInfo')
|
||||
},
|
||||
methods: {
|
||||
getReportInfo() {
|
||||
this.loading = true
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$router.currentRoute.query.trialId
|
||||
}
|
||||
|
||||
getReadingReportEvaluation(params).then(res => {
|
||||
this.readingTaskState = res.Result.ReadingTaskState
|
||||
this.tumorEvaluate = res.Result.TumorEvaluate ? parseInt(res.Result.TumorEvaluate) : null
|
||||
var questions = []
|
||||
this.answerArr = []
|
||||
res.Result.TaskQuestions.forEach((item, index) => {
|
||||
if (!([3, 4, 5, 6, 2].includes(item.QuestionMark))) {
|
||||
const obj = item
|
||||
obj.Answers = {}
|
||||
|
||||
item.Answer.forEach(i => {
|
||||
if (item.DictionaryCode) {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||
} else {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer
|
||||
}
|
||||
})
|
||||
if (item.QuestionType === 13) {
|
||||
this.currentEvaluateResult = obj.Answers[this.visitTaskId]
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
|
||||
}
|
||||
if (item.QuestionType === 14) {
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
|
||||
}
|
||||
if (item.Childrens && item.Childrens.length > 0) {
|
||||
obj.Childrens = this.getQuestions(item.Childrens, obj.IsShowInDicom)
|
||||
}
|
||||
questions.push(obj)
|
||||
}
|
||||
})
|
||||
this.taskQuestions = questions
|
||||
this.visitTaskList = res.Result.VisitTaskList
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getQuestions(questions, isShowInDicom) {
|
||||
const arr = []
|
||||
if (questions.length !== 0) {
|
||||
questions.forEach((item) => {
|
||||
if (!([3, 4, 5, 6, 2].includes(item.QuestionMark))) {
|
||||
const obj = item
|
||||
obj.IsShowInDicom = isShowInDicom
|
||||
obj.Answers = {}
|
||||
if (item.RowIndex > 0) {
|
||||
var idx = item.Childrens.findIndex(i => i.QuestionMark === 4)
|
||||
if (idx > -1) {
|
||||
if (item.Childrens[idx].Answer.length > 0) {
|
||||
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
|
||||
// var splitOrMergeType = isNaN(parseInt(item.SplitOrMergeType)) ? '' : parseInt(item.SplitOrMergeType)
|
||||
if (item.SplitOrMergeLesionName && k > -1) {
|
||||
obj.QuestionName = `${obj.QuestionName} -- ${item.Childrens[idx].Answer[k].Answer} (Split from ${item.SplitOrMergeLesionName})`
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else if (!item.SplitOrMergeLesionName && k > -1) {
|
||||
obj.QuestionName = `${obj.QuestionName} -- ${item.Childrens[idx].Answer[k].Answer}`
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else {
|
||||
obj.QuestionName = `${obj.QuestionName} `
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
item.Answer.forEach(i => {
|
||||
if (item.DictionaryCode) {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||
} else {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer
|
||||
}
|
||||
})
|
||||
if (item.QuestionType === 13) {
|
||||
this.currentEvaluateResult = obj.Answers[this.visitTaskId]
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 13 })
|
||||
}
|
||||
if (item.QuestionType === 14) {
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
|
||||
}
|
||||
if (item.Childrens.length >= 1) {
|
||||
obj.Childrens = this.getQuestions(item.Childrens, isShowInDicom)
|
||||
}
|
||||
arr.push(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr
|
||||
},
|
||||
handleEvaluateResultChange(val) {
|
||||
this.currentEvaluateResult = parseInt(val)
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 13)
|
||||
this.answerArr[idx].answer = val
|
||||
},
|
||||
evaluateReasonChange(val) {
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 14)
|
||||
this.answerArr[idx].answer = val
|
||||
},
|
||||
async handleConfirm() {
|
||||
await this.handleSave(false)
|
||||
await this.verifyVisitTaskQuestions()
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
},
|
||||
verifyVisitTaskQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId }).then(res => {
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleResize() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportList.doLayout()
|
||||
})
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.visitTaskId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
submitDicomVisitTask(params).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
this.signVisible = false
|
||||
// window.location.reload()
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
var token = getToken()
|
||||
var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
var subjectId = this.$router.currentRoute.query.subjectId
|
||||
var trialId = this.$router.currentRoute.query.trialId
|
||||
|
||||
this.$router.push({
|
||||
path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(_ => {
|
||||
this.loading = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
})
|
||||
},
|
||||
handleSave(isPrompt) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var evaluateResult = ''
|
||||
var evaluateAjustReason = ''
|
||||
this.answers = []
|
||||
var isExistEvaluateResult = false
|
||||
this.answerArr.map(item => {
|
||||
if (item.questionType === 13) {
|
||||
evaluateResult = item.answer
|
||||
isExistEvaluateResult = true
|
||||
}
|
||||
if (item.questionType === 14) {
|
||||
evaluateAjustReason = item.answer
|
||||
}
|
||||
this.answers.push({ id: item.id, answer: item.answer })
|
||||
})
|
||||
if (isExistEvaluateResult && evaluateResult === null) {
|
||||
this.$confirm('请将疗效评估信息填写完整', {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
reject()
|
||||
return
|
||||
}
|
||||
if (isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
|
||||
this.$confirm('请填写整体评估调整原因', {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
reject()
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: this.answers
|
||||
}
|
||||
changeDicomReadingQuestionAnswer(params).then(res => {
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.report-wrapper{
|
||||
|
||||
height: 100%;
|
||||
// background-color: #fff;
|
||||
background-color: #000;
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.report-header{
|
||||
display: flex;
|
||||
}
|
||||
.el-card{
|
||||
background-color: #000;
|
||||
color: #ffffff;
|
||||
border:none;
|
||||
}
|
||||
// >>>.el-table__cell{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
// >>>.el-table{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
// >>>.el-table__cell{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
|
||||
>>>.el-table, .el-table__expanded-cell {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
|
||||
>>>.el-table th, .el-table tr {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
>>>.el-table__body tr > td{
|
||||
background-color:#000 !important;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
>>>.el-table__body tr:hover > td{
|
||||
background-color:#858282 !important;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
>>>.el-table--border th.gutter:last-of-type{
|
||||
border: none;
|
||||
}
|
||||
>>>.el-card__header{
|
||||
border: none;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,153 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="ecrf-wrapper">
|
||||
<el-form
|
||||
v-if="questions.length > 0"
|
||||
ref="questions"
|
||||
size="small"
|
||||
:model="questionForm"
|
||||
>
|
||||
<QuestionItem
|
||||
v-for="question of questions"
|
||||
:key="question.Id"
|
||||
:question="question"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:visit-task-id="visitTaskId"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
|
||||
<el-form-item v-if="readingTaskState < 2">
|
||||
<div style="text-align:right">
|
||||
<el-button size="mini" @click="handleSave">{{ $t('common:button:save') }}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { saveImageQuality } from '@/api/trials'
|
||||
import QuestionItem from './QuestionItem'
|
||||
import DicomEvent from './DicomEvent'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'ECRF',
|
||||
components: {
|
||||
QuestionItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
questions: [],
|
||||
questionForm: {},
|
||||
readingTaskState: 2,
|
||||
visitTaskId: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList'])
|
||||
},
|
||||
mounted() {
|
||||
DicomEvent.$on('setReadingState', readingTaskState => {
|
||||
this.readingTaskState = readingTaskState
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setReadingState')
|
||||
},
|
||||
methods: {
|
||||
async getQuestions(visitTaskId) {
|
||||
this.visitTaskId = visitTaskId
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
|
||||
|
||||
if (idx > -1) {
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
var questions = this.visitTaskList[idx].Questions
|
||||
questions.map((v) => {
|
||||
if (v.Type === 'group' && v.Childrens.length === 0) return
|
||||
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
|
||||
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
|
||||
}
|
||||
if (v.Childrens.length > 0) {
|
||||
this.setChild(v.Childrens)
|
||||
}
|
||||
})
|
||||
this.questions = questions
|
||||
}
|
||||
// loading.close()
|
||||
},
|
||||
setChild(obj) {
|
||||
obj.forEach(i => {
|
||||
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
|
||||
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
|
||||
}
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.setChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs['questions'].validate((valid) => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: answers
|
||||
|
||||
}
|
||||
saveImageQuality(params).then(res => {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.loading = false
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
DicomEvent.$emit('refreshVisitList', this.visitTaskId)
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.questionForm[v] = null
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.questionForm[obj.key] = obj.val
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ecrf-wrapper{
|
||||
>>>.el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
}
|
||||
>>>.el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
>>>.el-form-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
>>>.el-form-item__content{
|
||||
flex: 1;
|
||||
}
|
||||
>>>.el-button--mini, .el-button--mini.is-round {
|
||||
padding: 7px 10px;
|
||||
}
|
||||
.el-form-item__content
|
||||
.el-select{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,708 @@
|
|||
/* eslint-disable vue/this-in-template */
|
||||
<template>
|
||||
<div v-loading="loading" class="viewerContainer">
|
||||
<!-- <div class="viewerBanner" /> -->
|
||||
<div class="viewerContentWrapper">
|
||||
<div class="viewerLeftSidePanel">
|
||||
<div id="listWrapper" class="sidePanelBody">
|
||||
<div class="sidePanelThumbs">
|
||||
<el-tabs v-model="activeName" type="border-card">
|
||||
<el-tab-pane :label="$t('trials:dicom-show:nowStudy')" name="first">
|
||||
<div class="studyDesc">
|
||||
{{ studyCode }}
|
||||
</div>
|
||||
<div class="studyDesc">
|
||||
{{ description }}
|
||||
</div>
|
||||
<div v-if="seriesCount" class="studyDesc">
|
||||
{{ modality }} : {{ seriesCount }} Series
|
||||
</div>
|
||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||
<div class="viewerSidethumbinner">
|
||||
<div
|
||||
v-for="(item, index) in seriesList"
|
||||
:key="index"
|
||||
:class="{'viewerSideActive': index==0}"
|
||||
style="position: relative;margin-bottom:5px;border-radius: 2px;border: 1px solid #404040;"
|
||||
series-type="current"
|
||||
@click="showSeriesImage($event,index,item)"
|
||||
>
|
||||
<div class="viewernavigatorwrapper">
|
||||
<el-image
|
||||
class="image-preview"
|
||||
style="height:72px;width:72px;"
|
||||
:src="item.previewImageUrl"
|
||||
fit="fill"
|
||||
/>
|
||||
<div class="viewernavitextwrapper">
|
||||
<div v-if="item.keySeries" style="padding: 1px;color:red">
|
||||
Key Images
|
||||
</div>
|
||||
<div v-else style="padding: 1px;">
|
||||
#{{ item.seriesNumber }}
|
||||
</div>
|
||||
<div v-show="item.instanceCount" style="padding: 1px;">
|
||||
{{ item.modality }}: {{ item.instanceCount }} image
|
||||
</div>
|
||||
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
|
||||
T: {{ item.sliceThickness }}
|
||||
</div>
|
||||
<div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ item.description }}
|
||||
</div>
|
||||
<div v-if="!item.keySeries" style="padding: 1px;">
|
||||
{{ item.prefetchInstanceCount }}/{{ item.instanceCount }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showDelete" @click.stop="">
|
||||
|
||||
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="item.isReading"
|
||||
size="mini"
|
||||
@change="changeReadingStatus($event, item)"
|
||||
/>
|
||||
|
||||
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="item.isDeleted"
|
||||
size="mini"
|
||||
@change="changeDeleteStatus($event, item)"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount">
|
||||
<el-progress :percentage="parseInt(((item.prefetchInstanceCount/item.instanceCount)*100).toFixed(2))" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="viewerContent">
|
||||
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" />
|
||||
</div>
|
||||
<!-- <div class="viewerRightSidePanel">
|
||||
<dicom-tools />
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dicomParser from 'dicom-parser'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import dicomViewer from '@/components/Dicom/DicomViewer'
|
||||
import { getStudyInfo, getSeriesList } from '@/api/reading'
|
||||
import { getInstanceList, setSeriesStatus } from '@/api/trials'
|
||||
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
|
||||
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
|
||||
export default {
|
||||
components: {
|
||||
'dicom-viewer': dicomViewer
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
trialId: '',
|
||||
studyId: '',
|
||||
tpCode: '',
|
||||
baseLine: null,
|
||||
studyCode: '',
|
||||
modality: '',
|
||||
description: '',
|
||||
seriesCount: 0,
|
||||
seriesList: [],
|
||||
currentSeriesIndex: -1,
|
||||
arr: [],
|
||||
activeName: 'first',
|
||||
tpList: [],
|
||||
visitNum: 0,
|
||||
labels: {},
|
||||
type: '',
|
||||
currentRelationIndex: [],
|
||||
cachedImages: [],
|
||||
isLoadedAll: false,
|
||||
studyList: {},
|
||||
currentStudy: '',
|
||||
previewImageCount: 0,
|
||||
relationStudyList: [],
|
||||
isStartLoad: false,
|
||||
firstInstanceId: '',
|
||||
showDelete: false,
|
||||
loading: false,
|
||||
imageList: []
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
||||
|
||||
this.visitNum = this.$router.currentRoute.query.visitNum ? parseInt(this.$router.currentRoute.query.visitNum) : 0
|
||||
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
||||
// cornerstone.events.addEventListener('datasetscachechanged', this.datasetsCacheChanged)
|
||||
if (this.$router.currentRoute.query.TokenKey) {
|
||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||
changeURLStatic('TokenKey', '')
|
||||
}
|
||||
this.studyId = this.$router.currentRoute.query.studyId
|
||||
if (this.type === 'Series') {
|
||||
// this.initStudy()
|
||||
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
|
||||
this.initSeries()
|
||||
} else if (this.type === 'Study') {
|
||||
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
|
||||
this.loadStudy()
|
||||
} else if (this.type === 'Share') {
|
||||
this.loadStudy()
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
requestPoolManager.stopTaskTimer()
|
||||
},
|
||||
methods: {
|
||||
loadStudy() {
|
||||
var scope = this
|
||||
getStudyInfo(scope.studyId).then(data => {
|
||||
if (data.IsSuccess) {
|
||||
scope.studyCode = data.Result.StudyCode
|
||||
scope.modality = data.Result.Modalities
|
||||
scope.seriesCount = data.Result.SeriesCount
|
||||
scope.description = data.Result.Description
|
||||
var url = `/series/list/${scope.studyId}`
|
||||
scope.getSeriesList(url)
|
||||
}
|
||||
})
|
||||
},
|
||||
getSeriesList(url) {
|
||||
var scope = this
|
||||
getSeriesList(url).then(data => {
|
||||
if (data.IsSuccess) {
|
||||
const { Result } = data
|
||||
var seriesList = []
|
||||
Result.forEach(function(item) {
|
||||
const imageIds = []
|
||||
item.InstancePathList.forEach((path) => {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
|
||||
})
|
||||
var subjectVisitId = scope.$router.currentRoute.query.subjectVisitId
|
||||
var studyId = scope.$router.currentRoute.query.studyId
|
||||
var trialId = scope.$router.currentRoute.query.trialId
|
||||
seriesList.push({
|
||||
trialId,
|
||||
subjectVisitId,
|
||||
studyId,
|
||||
imageIds: imageIds,
|
||||
seriesId: item.Id,
|
||||
seriesUid: item.SeriesInstanceUid,
|
||||
seriesNumber: item.SeriesNumber,
|
||||
sliceThickness: item.SliceThickness,
|
||||
modality: item.Modality,
|
||||
description: item.Description,
|
||||
isReading: item.IsReading,
|
||||
isDeleted: item.IsDeleted,
|
||||
previewImageUrl: item.ImageResizePath ? scope.OSSclientConfig.basePath + item.ImageResizePath : `/api/series/preview/${item.Id}`,
|
||||
instanceCount: item.InstanceCount,
|
||||
prefetchInstanceCount: 0,
|
||||
hasLabel: item.HasLabel,
|
||||
keySeries: item.KeySeries,
|
||||
tpCode: scope.tpCode,
|
||||
loadStatus: false,
|
||||
imageloadedArr: []
|
||||
})
|
||||
})
|
||||
scope.seriesList = seriesList
|
||||
if (scope.seriesList.length > 0) {
|
||||
scope.$refs.dicomViewer.loadImageStack(scope.seriesList[0], scope.labels[scope.tpCode])
|
||||
scope.firstInstanceId = scope.seriesList[0].imageIds[0]
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
initSeries() {
|
||||
this.studyCode = this.$router.currentRoute.query.studyCode
|
||||
this.modality = this.$router.currentRoute.query.modality
|
||||
this.seriesCount = 1
|
||||
this.description = this.$router.currentRoute.query.description
|
||||
var seriesId = this.$router.currentRoute.query.seriesId
|
||||
var seriesNumber = this.$router.currentRoute.query.seriesNumber
|
||||
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
||||
var studyId = this.$router.currentRoute.query.studyId
|
||||
var trialId = this.$router.currentRoute.query.trialId
|
||||
getInstanceList(seriesId).then(res => {
|
||||
if (!res.Result || (res.Result && res.Result.length === 0)) return
|
||||
var seriesInstanceUid = res.Result[0].SeriesInstanceUid
|
||||
var sliceLocation = res.Result[0].SliceLocation
|
||||
var isReading = res.Result[0].IsReading
|
||||
var isDeleted = res.Result[0].IsDeleted
|
||||
var seriesList = []
|
||||
var imageIds = []
|
||||
res.Result.forEach(instance => {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
|
||||
})
|
||||
seriesList.push({
|
||||
trialId,
|
||||
subjectVisitId,
|
||||
studyId,
|
||||
imageIds: imageIds,
|
||||
seriesId: seriesId,
|
||||
seriesUid: seriesInstanceUid,
|
||||
seriesNumber: seriesNumber,
|
||||
sliceThickness: sliceLocation,
|
||||
modality: this.modality,
|
||||
description: this.description,
|
||||
isReading,
|
||||
isDeleted,
|
||||
previewImageUrl: res.OtherInfo.ImageResizePath ? scope.OSSclientConfig.basePath + res.OtherInfo.ImageResizePath : res.OtherInfo.ImageResizePath,
|
||||
instanceCount: res.Result.length,
|
||||
prefetchInstanceCount: 0,
|
||||
loadStatus: false,
|
||||
imageloadedArr: []
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
if (this.seriesList.length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.loadAllImages()
|
||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[0])
|
||||
this.firstInstanceId = this.seriesList[0].imageIds[0]
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
showSeriesImage(e, seriesIndex, series) {
|
||||
// if (seriesIndex === this.currentSeriesIndex) return
|
||||
const element = e.currentTarget
|
||||
const elements = document.querySelectorAll('[series-type]')
|
||||
Array.from(elements).forEach((e) => {
|
||||
e.classList.remove('viewerSideActive')
|
||||
})
|
||||
element.classList.add('viewerSideActive')
|
||||
this.currentSeriesIndex = seriesIndex
|
||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
|
||||
if (!series.loadStatus) {
|
||||
series.isLoading = true
|
||||
var p = new Date().getTime()
|
||||
series.imageIds.map((imageId, i) => {
|
||||
var priority = ''
|
||||
if (i === 0) {
|
||||
priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
|
||||
} else {
|
||||
priority = p - 1
|
||||
}
|
||||
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
|
||||
})
|
||||
}
|
||||
},
|
||||
initStudy() {
|
||||
this.studyCode = this.$router.currentRoute.query.studyCode
|
||||
this.modality = this.$router.currentRoute.query.modality
|
||||
this.seriesCount = 1
|
||||
this.description = this.$router.currentRoute.query.description
|
||||
if (this.$router.currentRoute.query.series) {
|
||||
const seriesInfo = JSON.parse(this.$router.currentRoute.query.series)
|
||||
var seriesList = []
|
||||
const imageIds = []
|
||||
seriesInfo.InstancePathList.forEach((path) => {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
|
||||
})
|
||||
seriesList.push({
|
||||
imageIds: imageIds,
|
||||
seriesId: seriesInfo.Id,
|
||||
seriesUid: seriesInfo.SeriesInstanceUid,
|
||||
seriesNumber: seriesInfo.SeriesNumber,
|
||||
sliceThickness: seriesInfo.SliceThickness,
|
||||
modality: seriesInfo.Modality,
|
||||
description: seriesInfo.Description,
|
||||
previewImageUrl: seriesInfo.ImageResizePath ? this.OSSclientConfig.basePath + seriesInfo.ImageResizePath : `/api/series/preview/${seriesInfo.Id}`,
|
||||
instanceCount: seriesInfo.InstanceCount,
|
||||
prefetchInstanceCount: 0,
|
||||
hasLabel: seriesInfo.HasLabel,
|
||||
keySeries: seriesInfo.KeySeries,
|
||||
loadStatus: false,
|
||||
imageloadedArr: []
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
if (this.seriesList.length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.loadAllImages()
|
||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[0])
|
||||
this.firstInstanceId = this.seriesList[0].imageIds[0]
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteSeries() {
|
||||
this.loading = true
|
||||
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
||||
var studyId = this.$router.currentRoute.query.studyId
|
||||
var seriesId = this.$router.currentRoute.query.seriesId
|
||||
// trialId, subjectVisitId, studyId, seriesId, state
|
||||
setSeriesStatus(this.trialId, subjectVisitId, studyId, seriesId, 5).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
|
||||
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
changeReadingStatus(callback, data) {
|
||||
let statusStr = ''
|
||||
if (callback) {
|
||||
statusStr = this.$t('trials:audit:label:setSeriesReading')
|
||||
data.isReading = false
|
||||
} else {
|
||||
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
|
||||
data.isReading = true
|
||||
}
|
||||
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
|
||||
this.$confirm(message, {
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const state = data.isReading ? 1 : 2
|
||||
this.loading = true
|
||||
|
||||
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
data.isReading = !data.isReading
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
}).catch(() => {})
|
||||
},
|
||||
changeDeleteStatus(callback, data) {
|
||||
let statusStr = ''
|
||||
if (callback) {
|
||||
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
|
||||
data.isDeleted = false
|
||||
} else {
|
||||
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
|
||||
data.isDeleted = true
|
||||
}
|
||||
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
|
||||
this.$confirm(message, {
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const state = data.isDeleted ? 5 : 4
|
||||
this.loading = true
|
||||
// var trialId = this.$router.currentRoute.query.trialId
|
||||
// var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
|
||||
// var studyId = this.$router.currentRoute.query.studyId
|
||||
// var seriesId = this.$router.currentRoute.query.seriesId
|
||||
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
data.isDeleted = !data.isDeleted
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
}).catch(() => {})
|
||||
},
|
||||
loadAllImages() {
|
||||
var priority = new Date().getTime()
|
||||
this.seriesList.forEach(series => {
|
||||
series.imageIds.forEach(imageId => {
|
||||
priority--
|
||||
// this.load(imageId, series.seriesId, priority)
|
||||
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
|
||||
})
|
||||
})
|
||||
if (this.imageList.length > 0) {
|
||||
this.loopLoad()
|
||||
}
|
||||
},
|
||||
loopLoad() {
|
||||
if (this.imageList.length > 0) {
|
||||
requestPoolManager.startTaskTimer()
|
||||
this.imageList.map(image => {
|
||||
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
|
||||
this.imageLoaded(image, res.data.string('x0020000e'))
|
||||
})
|
||||
})
|
||||
|
||||
this.imageList = []
|
||||
}
|
||||
},
|
||||
load(imageId, seriesId, priority = 999) {
|
||||
return new Promise((resolve, reject) => {
|
||||
requestPoolManager.loadAndCacheImagePlus(imageId, seriesId, priority).then(res => {
|
||||
if (!res) return
|
||||
this.imageLoaded(imageId, res.data.string('x0020000e'))
|
||||
resolve(res)
|
||||
}).catch(e => {
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
},
|
||||
imageLoaded(imageId, seriesUid) {
|
||||
var seriesIndex = -1
|
||||
for (let i = 0; i < this.seriesList.length; ++i) {
|
||||
if (this.seriesList[i].seriesUid === seriesUid) {
|
||||
seriesIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (seriesIndex < 0) return
|
||||
|
||||
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
|
||||
if (imageIdIndex < 0) return
|
||||
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
|
||||
++this.seriesList[seriesIndex].prefetchInstanceCount
|
||||
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
|
||||
|
||||
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
|
||||
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.seriesList[seriesIndex].loadStatus = true
|
||||
// if (!this.isLoadedAll) {
|
||||
// this.loadAllImages()
|
||||
// }
|
||||
}
|
||||
}
|
||||
},
|
||||
datasetsCacheChanged(e) {
|
||||
// const uri = e.detail.uri
|
||||
const cacheInfo = e.detail.cacheInfo
|
||||
const cacheSizeInBytes = cacheInfo.cacheSizeInBytes
|
||||
if (cacheSizeInBytes >= maximumSizeInBytes) {
|
||||
// this.unload()
|
||||
}
|
||||
},
|
||||
unload() {
|
||||
this.cachedImages.sort(this.compare)
|
||||
cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.unload(this.cachedImages[0].uri)
|
||||
this.cachedImages.splice(0, 1)
|
||||
},
|
||||
compare(a, b) {
|
||||
if (a.timeStamp > b.timeStamp) {
|
||||
return -1
|
||||
}
|
||||
if (a.timeStamp < b.timeStamp) {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
},
|
||||
cornerstoneImageLoaded(e) {
|
||||
console.log('dicom-study')
|
||||
if (this.firstInstanceId === e.detail.image.imageId && !this.isStartLoad) {
|
||||
// 初始化图像加载完成时,自动下载
|
||||
this.loadAllImages()
|
||||
this.isStartLoad = true
|
||||
// requestPoolManager.executeTask()
|
||||
}
|
||||
const uri = e.detail.image.sharedCacheKey
|
||||
const index = this.cachedImages.findIndex(item => item.uri === uri)
|
||||
if (index === -1) {
|
||||
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
|
||||
} else {
|
||||
this.cachedImages[index].timestamp = new Date().getTime()
|
||||
}
|
||||
// loadedDataSets[uri].dataSet.byteArray.length
|
||||
// console.log(this.cachedImages.length)
|
||||
// console.log(cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.getInfo().cacheSizeInBytes)
|
||||
// const imageId = e.detail.image.imageId
|
||||
var imageId = e.detail.image.imageId
|
||||
var seriesUid = e.detail.image.data.string('x0020000e')
|
||||
var seriesIndex = -1
|
||||
for (let i = 0; i < this.seriesList.length; ++i) {
|
||||
if (this.seriesList[i].seriesUid === seriesUid) {
|
||||
seriesIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (seriesIndex < 0) return
|
||||
|
||||
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
|
||||
if (imageIdIndex < 0) return
|
||||
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
|
||||
++this.seriesList[seriesIndex].prefetchInstanceCount
|
||||
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
|
||||
|
||||
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
|
||||
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.seriesList[seriesIndex].loadStatus = true
|
||||
// if (!this.isLoadedAll) {
|
||||
// this.loadAllImages()
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.viewerContainer .el-tabs--border-card{
|
||||
background:none;
|
||||
border: none;
|
||||
}
|
||||
.viewerContainer .el-tabs__item{
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.viewerContainer .el-tabs--border-card>.el-tabs__content{
|
||||
padding: 5px 0px 0px 0px;
|
||||
}
|
||||
.viewerContainer ::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
.viewerContainer ::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.viewerContainer .relationVisit{
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer{
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
}
|
||||
.viewerContainer .viewerBanner {
|
||||
background: linear-gradient(0,#444,#222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.viewerContainer .viewerContentWrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.viewerContainer .viewerContentWrapper>div {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel {
|
||||
width: 215px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.viewerContainer .viewerContentWrapper>div>.sidePanelBody {
|
||||
background: rgba(50,50,50,1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
}
|
||||
.viewerContainer .viewerContentWrapper>div>div.sidePanelBody>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.viewerContainer .studyDesc{
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
background: rgb(88 84 83);
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
.viewerContainer .ps {
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
|
||||
display: flex;
|
||||
width: 210px;
|
||||
height: 84px;
|
||||
padding: 1px 2px 1px 8px;
|
||||
margin: 6px 0 6px 1px;
|
||||
/* border-radius: 2px;
|
||||
border: 1px solid #404040; */
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress__text{
|
||||
display: none;
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
.viewerContainer .ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex:1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerContainer .viewerSideActive {
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
}
|
||||
.viewerContainer .viewerContent {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
}
|
||||
/* .viewerRightSidePanel {
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
background-color: #323232;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-left: 2px;
|
||||
border: 1px solid blueviolet;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
} */
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,419 @@
|
|||
<template>
|
||||
<div class="viewerContainer">
|
||||
<div class="viewerContentWrapper">
|
||||
<div class="viewerLeftSidePanel">
|
||||
<div id="listWrapper" class="sidePanelBody">
|
||||
<div class="sidePanelThumbs">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="当前序列" name="current-study">
|
||||
<div class="text-desc">
|
||||
{{ studyCode }}
|
||||
</div>
|
||||
<div class="text-desc">
|
||||
{{ description }}
|
||||
</div>
|
||||
<div v-if="seriesCount" class="text-desc">
|
||||
{{ modality }} : {{ seriesCount }} Series
|
||||
</div>
|
||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||
<div class="viewerSidethumbinner">
|
||||
<div
|
||||
v-for="(item, index) in seriesList"
|
||||
|
||||
:key="index"
|
||||
class="viewernavigatorwrapper"
|
||||
:class="{'viewerSideActive': index==0}"
|
||||
style="position: relative;"
|
||||
series-type="current"
|
||||
@click="showSeriesImage($event,index)"
|
||||
>
|
||||
<el-image
|
||||
class="image-preview"
|
||||
style="height:72px;width:72px;"
|
||||
:src="item.previewImageUrl"
|
||||
fit="fill"
|
||||
/>
|
||||
<div class="viewernavitextwrapper">
|
||||
<div style="padding: 1px;">
|
||||
#{{ item.seriesNumber }}
|
||||
</div>
|
||||
<div v-show="item.instanceCount" style="padding: 1px;">
|
||||
{{ item.modality }}: {{ item.instanceCount }} image
|
||||
</div>
|
||||
<div v-show=" item.sliceThickness" style="padding: 1px;">
|
||||
T: {{ item.sliceThickness }}
|
||||
</div>
|
||||
<div v-show="item.description" style="padding: 1x;">
|
||||
{{ item.description }}
|
||||
</div>
|
||||
<div style="padding: 1px;">
|
||||
{{ item.prefetchInstanceCount }}/{{ item.instanceCount }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
|
||||
<el-progress v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount" :percentage="Number(item.prefetchInstanceCount/item.instanceCount)*100" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="viewerContent">
|
||||
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as dicomParser from 'dicom-parser'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import dicomViewer from '@/components/Dicom/DicomViewer'
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import store from '@/store'
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
|
||||
// cornerstoneWADOImageLoader.webWorkerManager.initialize({
|
||||
// webWorkerPath: './webWorker.js',
|
||||
// taskConfiguration: {
|
||||
// 'decodeTask': {
|
||||
// codecsPath: './dicomCodecs.js'
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
|
||||
export default {
|
||||
name: 'DicomsOfSeries',
|
||||
components: {
|
||||
'dicom-viewer': dicomViewer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
studyCode: '',
|
||||
modality: '',
|
||||
seriesCount: 0,
|
||||
description: '',
|
||||
seriesList: [],
|
||||
cachedImages: [],
|
||||
isStartLoad: false,
|
||||
firstInstanceId: ''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
store.dispatch('user/setToken', this.$router.currentRoute.query.token)
|
||||
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
||||
this.initStudy()
|
||||
},
|
||||
beforeDestroy() {
|
||||
requestPoolManager.stopTaskTimer()
|
||||
},
|
||||
methods: {
|
||||
// 格式化序列信息
|
||||
initStudy() {
|
||||
this.studyCode = this.$router.currentRoute.query.studyCode
|
||||
this.modality = this.$router.currentRoute.query.modality
|
||||
this.seriesCount = 1
|
||||
this.description = this.$router.currentRoute.query.description
|
||||
if (this.$router.currentRoute.query.series) {
|
||||
const seriesInfo = JSON.parse(this.$router.currentRoute.query.series)
|
||||
var seriesList = []
|
||||
const imageIds = []
|
||||
// seriesInfo.InstanceList.forEach(function(item) {
|
||||
// imageIds.push(`wadouri:/api/instance/content/${item}`)
|
||||
// })
|
||||
seriesInfo.InstanceList.forEach((id) => {
|
||||
imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`)
|
||||
})
|
||||
seriesList.push({
|
||||
imageIds: imageIds,
|
||||
seriesId: seriesInfo.Id,
|
||||
seriesUid: seriesInfo.SeriesInstanceUid,
|
||||
seriesNumber: seriesInfo.SeriesNumber,
|
||||
sliceThickness: seriesInfo.SliceThickness,
|
||||
modality: seriesInfo.Modality,
|
||||
description: seriesInfo.Description,
|
||||
previewImageUrl: `/api/series/preview/${seriesInfo.Id}`,
|
||||
instanceCount: seriesInfo.InstanceCount,
|
||||
prefetchInstanceCount: 0,
|
||||
loadStatus: false,
|
||||
imageloadedArr: []
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
if (this.seriesList.length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[0])
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
showSeriesImage(e, seriesIndex) {
|
||||
const element = e.currentTarget
|
||||
const elements = document.querySelectorAll('[series-type]')
|
||||
Array.from(elements).forEach((e) => {
|
||||
e.classList.remove('viewerSideActive')
|
||||
})
|
||||
element.classList.add('viewerSideActive')
|
||||
this.currentSeriesIndex = seriesIndex
|
||||
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
|
||||
},
|
||||
loadAllImages() {
|
||||
this.seriesList.forEach(series => {
|
||||
series.imageIds.forEach(imageId => {
|
||||
this.load(imageId, series.seriesId)
|
||||
})
|
||||
})
|
||||
},
|
||||
// load(imageId, priority = 999) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// const imageTask = this.buildImageRequestTask(imageId, { priority })
|
||||
// requestPoolManager.addTaskIntoPool(imageTask).then((res) => {
|
||||
// resolve(res)
|
||||
// }).catch(e => {
|
||||
// reject(e)
|
||||
// console.log(e)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
load(imageId, seriesId, priority = 999) {
|
||||
return new Promise((resolve, reject) => {
|
||||
requestPoolManager.loadAndCacheImagePlus(imageId, seriesId, priority).then(res => {
|
||||
if (!res) return
|
||||
this.imageLoaded(imageId, res.data.string('x0020000e'))
|
||||
resolve(res)
|
||||
}).catch(e => {
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
},
|
||||
imageLoaded(imageId, seriesUid) {
|
||||
var seriesIndex = -1
|
||||
for (let i = 0; i < this.seriesList.length; ++i) {
|
||||
if (this.seriesList[i].seriesUid === seriesUid) {
|
||||
seriesIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (seriesIndex < 0) return
|
||||
|
||||
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
|
||||
if (imageIdIndex < 0) return
|
||||
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
|
||||
++this.seriesList[seriesIndex].prefetchInstanceCount
|
||||
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
|
||||
|
||||
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
|
||||
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.seriesList[seriesIndex].loadStatus = true
|
||||
}
|
||||
}
|
||||
},
|
||||
buildImageRequestTask(imageId, config = {}) {
|
||||
return {
|
||||
key: imageId,
|
||||
...config,
|
||||
execute: () => {
|
||||
return cornerstone.loadAndCacheImage(imageId)
|
||||
}
|
||||
}
|
||||
},
|
||||
datasetsCacheChanged(e) {
|
||||
const cacheInfo = e.detail.cacheInfo
|
||||
const cacheSizeInBytes = cacheInfo.cacheSizeInBytes
|
||||
if (cacheSizeInBytes >= maximumSizeInBytes) {
|
||||
// 清理影像缓存
|
||||
}
|
||||
},
|
||||
// instance下载成功回调
|
||||
cornerstoneImageLoaded(e) {
|
||||
if (this.firstInstanceId === e.detail.image.imageId && !this.isStartLoad) {
|
||||
// 初始化图像加载完成时,自动下载
|
||||
this.loadAllImages()
|
||||
this.isStartLoad = true
|
||||
requestPoolManager.executeTask()
|
||||
}
|
||||
const uri = e.detail.image.sharedCacheKey
|
||||
const index = this.cachedImages.findIndex(item => item.uri === uri)
|
||||
if (index === -1) {
|
||||
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
|
||||
} else {
|
||||
this.cachedImages[index].timestamp = new Date().getTime()
|
||||
}
|
||||
var imageId = e.detail.image.imageId
|
||||
var seriesUid = e.detail.image.data.string('x0020000e')
|
||||
var seriesIndex = -1
|
||||
for (let i = 0; i < this.seriesList.length; ++i) {
|
||||
if (this.seriesList[i].seriesUid === seriesUid) {
|
||||
seriesIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if (seriesIndex < 0) return
|
||||
|
||||
const imageIdIndex = this.seriesList[seriesIndex].imageIds.indexOf(imageId)
|
||||
if (imageIdIndex < 0) return
|
||||
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
|
||||
++this.seriesList[seriesIndex].prefetchInstanceCount
|
||||
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
|
||||
|
||||
if (this.seriesList[seriesIndex].prefetchInstanceCount >= this.seriesList[seriesIndex].instanceCount) {
|
||||
this.seriesList[seriesIndex].prefetchInstanceCount = this.seriesList[seriesIndex].instanceCount
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.seriesList[seriesIndex].loadStatus = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.viewerContainer{
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
.el-tabs--border-card{
|
||||
background:none;
|
||||
border: none;
|
||||
}
|
||||
.el-tabs--border-card>.el-tabs__content{
|
||||
padding: 5px 0px 0px 0px;
|
||||
}
|
||||
.el-tabs__item{
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.relationVisit{
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerBanner {
|
||||
background: linear-gradient(0,#444,#222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.viewerContentWrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.viewerContentWrapper>div {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
}
|
||||
.viewerLeftSidePanel {
|
||||
width: 215px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.viewerContentWrapper>div>.sidePanelBody {
|
||||
background: rgba(50,50,50,1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
}
|
||||
.viewerContentWrapper>div>div.sidePanelBody>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.text-desc{
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
// background: rgb(88 84 83);
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
.ps {
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
}
|
||||
.viewerLeftSidePanel .viewernavigatorwrapper {
|
||||
display: flex;
|
||||
width: 210px;
|
||||
height: 84px;
|
||||
padding: 1px 2px 1px 8px;
|
||||
margin: 6px 0 6px 1px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
.viewernavigatorwrapper .el-progress__text{
|
||||
display: none;
|
||||
}
|
||||
.viewernavigatorwrapper .el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
.ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex:1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerSideActive {
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
}
|
||||
.viewerContent {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,690 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="clinicalDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
label-width="130px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="类型" prop="Type">
|
||||
<el-select clearable v-model="form.Type" @change="((val)=>{typeChange(val, form)})">
|
||||
<el-option
|
||||
v-for="item of $d.Criterion_Question_Type"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 数值类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
label="数值类型"
|
||||
prop="ValueType"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择'}
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ValueType"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ValueType"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 数值单位 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
label="单位"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.Unit"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ValueUnit"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type === 'table'"
|
||||
label="表格类型标识"
|
||||
prop="LesionType"
|
||||
>
|
||||
<el-select
|
||||
clearable
|
||||
v-model="form.LesionType"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of lesionTypes"
|
||||
:key="item.Code"
|
||||
:value="parseInt(item.Code)"
|
||||
:label="$fd('LesionType',parseInt(item.Code))"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type === 'group'"
|
||||
label="分组名称"
|
||||
prop="GroupName"
|
||||
>
|
||||
<el-input v-model="form.GroupName" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group'"
|
||||
label="问题名称"
|
||||
prop="QuestionName"
|
||||
>
|
||||
<el-input v-model="form.QuestionName" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- <el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio'"
|
||||
label="选项"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.TypeValue"
|
||||
placeholder="选项请用‘|’分割多个选项"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<!-- 选项类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'"
|
||||
label="选项类型"
|
||||
prop="QuestionGenre"
|
||||
:rules="[
|
||||
{ required: form.Type !== 'calculation', message: '请选择'}
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.QuestionGenre"
|
||||
@change="((val)=>{questionGenreChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.TableQuestionType"
|
||||
v-show="item.value===0 || item.value===3"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 0"
|
||||
label="选项"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.TypeValue"
|
||||
placeholder="选项请用‘|’分割多个选项"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 3 "
|
||||
label="关联字典"
|
||||
prop="DictionaryCode"
|
||||
>
|
||||
<el-select clearable v-model="form.DictionaryCode" @change="() => {form.DefaultValue = null}">
|
||||
<el-option
|
||||
v-for="item of dicList"
|
||||
:key="item.Id"
|
||||
:label="item.Code"
|
||||
:value="item.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 3 "
|
||||
label="默认值"
|
||||
>
|
||||
<el-select clearable v-model="form.DefaultValue">
|
||||
<el-option
|
||||
v-for="item of form.DictionaryCode ? $d[form.DictionaryCode] : []"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 0 "
|
||||
label="默认值"
|
||||
>
|
||||
<el-select clearable v-model="form.DefaultValue">
|
||||
<el-option
|
||||
v-for="item of form.TypeValue ? form.TypeValue.split('|') : []"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="是否显示" prop="ShowQuestion">
|
||||
<el-radio-group
|
||||
v-model="form.ShowQuestion"
|
||||
@change="((val)=>{isShowQuestionChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ShowQuestion"
|
||||
:key="`ShowQuestion${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 显示时依赖父问题 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.ShowQuestion===1"
|
||||
label="显示依赖父问题"
|
||||
prop="ParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`ParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 显示时依赖父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId && form.ShowQuestion===1" label="显示触发值" prop="ParentTriggerValue">
|
||||
<el-select clearable v-model="form.ParentTriggerValue">
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'" label="是否裁判问题">
|
||||
<el-radio-group v-model="form.IsJudgeQuestion" @change="((val)=>{isJudgeQuestionChange(val, form)})">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.Type !== 'table'" label="是否必填" prop="IsRequired">
|
||||
<el-radio-group
|
||||
v-model="form.IsRequired"
|
||||
:disabled="form.IsJudgeQuestion===true || form.ShowQuestion===2"
|
||||
@change="((val)=>{isRequiredChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.QuestionRequired"
|
||||
:key="`QuestionRequired${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 父问题 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.IsRequired === 1"
|
||||
label="必填依赖父问题"
|
||||
prop="RelevanceId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.RelevanceId"
|
||||
clearable
|
||||
@change="((val)=>{relevanceQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`RelevanceId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 必填依赖的父问题触发值 -->
|
||||
<el-form-item
|
||||
v-if="form.RelevanceId && form.IsRequired === 1"
|
||||
label="必填触发值"
|
||||
prop="RelevanceValue"
|
||||
>
|
||||
<el-select clearable v-model="form.RelevanceValue">
|
||||
<el-option
|
||||
v-for="item of reParentTriggerValOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 父问题 -->
|
||||
<!-- <el-form-item v-if="form.Type !== 'group'" label="父问题">
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="item.QuestionId"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- 父问题触发值 -->
|
||||
<!-- <el-form-item v-if="form.ParentId" label="父问题触发值" prop="ParentTriggerValue">
|
||||
<el-select v-model="form.ParentTriggerValue">
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="问题分组">
|
||||
<el-select v-model="form.GroupName" clearable :disabled="isParentExistGroup">
|
||||
<el-option
|
||||
v-for="group of groupOptions"
|
||||
:key="group"
|
||||
:label="group"
|
||||
:value="group"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="全局阅片是否显示">
|
||||
<el-radio-group v-model="form.GlobalReadingShowType">
|
||||
<el-radio v-for="item of $d.GlobalReadingShowType" :label="item.value">{{item.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="问题标识"
|
||||
prop="QuestionType"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.QuestionType"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.QuestionType"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item v-if="form.Type !== 'group'" label="是否必填">
|
||||
<el-radio-group v-model="form.IsRequired" :disabled="form.IsJudgeQuestion===true">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
<el-form-item v-if="form.Type === 'upload'" label="最大上传个数">
|
||||
<el-input-number v-model="form.ImageCount" controls-position="right" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.Type !== 'summary'" label="注释">
|
||||
<el-input v-model="form.Remark" />
|
||||
</el-form-item>
|
||||
<el-form-item label="序号" prop="ShowOrder">
|
||||
<el-input-number
|
||||
v-model="form.ShowOrder"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type === 'table'" label="自增序号前缀">
|
||||
<el-input v-model="form.OrderMark" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type === 'table'" label="最大行数">
|
||||
<el-input-number
|
||||
v-model="form.MaxQuestionCount"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="是否在阅片显示">
|
||||
<el-radio-group v-model="form.IsShowInDicom">
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateReadingQuestionSystem, getSystemCriterionOtherQuestion, getSystemGroupNameList } from '@/api/dictionary'
|
||||
import { getCriterionLesionType } from '@/api/trials'
|
||||
import { getBasicConfigSelect } from '@/api/dictionary'
|
||||
export default {
|
||||
name: 'AddOrUpdateClinicalData',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
var validateTypeVal = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error(this.$t('common:ruleMessage:specify')))
|
||||
} else {
|
||||
var arr = value.split('|')
|
||||
if (new Set(arr).size !== arr.length) {
|
||||
callback(new Error('选项不允许存在相同值'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
validateTypeVal: validateTypeVal,
|
||||
form: {
|
||||
Id: '',
|
||||
ReadingQuestionCriterionSystemId: '',
|
||||
QuestionName: '',
|
||||
Type: 'input',
|
||||
ValueType: '',
|
||||
Unit: '',
|
||||
QuestionGenre: '',
|
||||
TypeValue: '',
|
||||
DictionaryCode: '',
|
||||
ParentId: '',
|
||||
ParentTriggerValue: '',
|
||||
ShowOrder: 0,
|
||||
ShowQuestion: 0,
|
||||
IsRequired: 2,
|
||||
IsJudgeQuestion: false,
|
||||
GroupName: '',
|
||||
Remark: '',
|
||||
ImageCount: 1,
|
||||
RelevanceId: '',
|
||||
RelevanceValue: '',
|
||||
LesionType: '',
|
||||
QuestionType: null,
|
||||
IsShowInDicom: false,
|
||||
OrderMark: '',
|
||||
MaxQuestionCount: 0,
|
||||
GlobalReadingShowType: 3,
|
||||
DefaultValue: null
|
||||
},
|
||||
rules: {
|
||||
Type: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
LesionType: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
QuestionName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }],
|
||||
QuestionGenre: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
TypeValue: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 500, message: '最大长度为 500' }],
|
||||
DictionaryCode: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ShowQuestion: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
IsRequired: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentTriggerValue: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
RelevanceId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
RelevanceValue: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
GroupName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }]
|
||||
},
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
parentOptions: [],
|
||||
parentTriggerValOptions: [],
|
||||
groupOptions: [],
|
||||
isParentExistGroup: false,
|
||||
lesionTypes: [],
|
||||
dicList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getGroupOptions()
|
||||
await this.getParentQuestions()
|
||||
await this.getLesionType()
|
||||
await this.getBasicConfigSelect()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
if (this.form.ParentId !== '' && this.form.ParentId !== null && this.form.GroupName !== '') {
|
||||
this.isParentExistGroup = true
|
||||
}
|
||||
if (this.form.ParentId) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === this.form.ParentId
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.parentTriggerValOptions = this.parentOptions[index].TypeValue.split('|')
|
||||
}
|
||||
}
|
||||
if (this.form.RelevanceId) {
|
||||
var i = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === this.form.RelevanceId
|
||||
})
|
||||
if (i !== -1) {
|
||||
this.reParentTriggerValOptions = this.parentOptions[i].TypeValue.split('|')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.clinicalDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
if (this.form.Type !== 'upload') {
|
||||
this.form.ImageCount = 0
|
||||
}
|
||||
addOrUpdateReadingQuestionSystem(this.form).then(res => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
getBasicConfigSelect() {
|
||||
getBasicConfigSelect('Reading_eCRF').then(res => {
|
||||
this.dicList = res.Result
|
||||
})
|
||||
},
|
||||
getGroupOptions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
criterionId: this.data.ReadingQuestionCriterionSystemId
|
||||
}
|
||||
getSystemGroupNameList(param).then(res => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
getParentQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
readingQuestionCriterionSystemId: this.data.ReadingQuestionCriterionSystemId,
|
||||
id: this.data.Id
|
||||
}
|
||||
getSystemCriterionOtherQuestion(param).then(res => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
questionGenreChange(val, form) {
|
||||
form.DictionaryCode = ''
|
||||
form.TypeValue = ''
|
||||
},
|
||||
// parentQuestionChange(val, form) {
|
||||
// this.isParentExistGroup = false
|
||||
// if (val) {
|
||||
// var index = this.parentOptions.findIndex(item => {
|
||||
// return item.QuestionId === val
|
||||
// })
|
||||
// if (index !== -1) {
|
||||
// this.parentTriggerValOptions = this.parentOptions[index].TypeValue.split('|')
|
||||
// if (this.parentOptions[index].GroupName) {
|
||||
// this.isParentExistGroup = true
|
||||
// form.GroupName = this.parentOptions[index].GroupName
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// form.ParentTriggerValue = ''
|
||||
// form.GroupName = ''
|
||||
// }
|
||||
// },
|
||||
typeChange(val, data) {
|
||||
if (val !== 'select' && val !== 'radio') {
|
||||
data.IsJudgeQuestion = false
|
||||
}
|
||||
if (val === 'table') {
|
||||
data.IsRequired = 2
|
||||
} else {
|
||||
data.LesionType = null
|
||||
}
|
||||
data.DictionaryCode = ''
|
||||
data.TypeValue = ''
|
||||
data.ValueType = ''
|
||||
data.Unit = ''
|
||||
},
|
||||
isShowQuestionChange(val, form) {
|
||||
console.log(val)
|
||||
if (val === 2) {
|
||||
form.IsRequired = 2
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
} else {
|
||||
form.ParentId = ''
|
||||
form.ParentTriggerValue = ''
|
||||
}
|
||||
},
|
||||
isRequiredChange(val, form) {
|
||||
if (val !== 1) {
|
||||
form.RelevanceId = ''
|
||||
form.RelevanceValue = ''
|
||||
}
|
||||
},
|
||||
parentQuestionChange(val, form) {
|
||||
this.isParentExistGroup = false
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.parentTriggerValOptions = this.parentOptions[index].TypeValue.split('|')
|
||||
if (this.parentOptions[index].GroupName) {
|
||||
this.isParentExistGroup = true
|
||||
form.GroupName = this.parentOptions[index].GroupName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
form.GroupName = ''
|
||||
}
|
||||
form.ParentTriggerValue = ''
|
||||
},
|
||||
relevanceQuestionChange(val, form) {
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
this.reParentTriggerValOptions = this.parentOptions[index].TypeValue.split('|')
|
||||
}
|
||||
}
|
||||
form.RelevanceValue = ''
|
||||
},
|
||||
isJudgeQuestionChange(val, form) {
|
||||
if (val) {
|
||||
form.IsRequired = 0
|
||||
}
|
||||
},
|
||||
getLesionType() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
criterionId: this.data.ReadingQuestionCriterionSystemId
|
||||
}
|
||||
getCriterionLesionType(param).then(res => {
|
||||
this.lesionTypes = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,256 @@
|
|||
<template>
|
||||
<div class="criterion-form-item">
|
||||
|
||||
<el-form-item
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && !!~question.RelevanceValueList.indexOf(questionForm[question.RelevanceId]))) && question.Type!=='group',
|
||||
message: $t('common:ruleMessage:specify'), trigger: ['blur']},
|
||||
]"
|
||||
:class="[question.ClinicalTableQuestionType==='group'?'mb':question.ClinicalTableQuestionType==='upload'?'uploadWrapper':'']"
|
||||
>
|
||||
<el-input
|
||||
v-if="question.ClinicalTableQuestionType==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="question.TableQuestionType === 2"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-if="question.ClinicalTableQuestionType==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="question.ClinicalTableQuestionType==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
clearable
|
||||
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode"
|
||||
>
|
||||
<template v-if="question.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[question.DataTableColumn]"
|
||||
:value="item[question.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-date-picker
|
||||
v-if="question.ClinicalTableQuestionType === 'time'"
|
||||
v-model="questionForm[question.Id]"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 200px"
|
||||
align="right"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
>
|
||||
</el-date-picker>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="question.ClinicalTableQuestionType==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-if="question.ClinicalTableQuestionType==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-input
|
||||
type="number"
|
||||
v-if="question.ClinicalTableQuestionType === 'number'"
|
||||
style="width: 200px"
|
||||
v-model="questionForm[question.Id]"
|
||||
>
|
||||
<template slot="append" v-if="question.Unit">{{question.Unit}}</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadReadingAnswerImage, getTrialOrganList, getCustomTableQuestionPreview } from '@/api/trials'
|
||||
export default {
|
||||
name: 'QuestionFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addOrEdit: { visible: false, title: '' },
|
||||
fileList: [],
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: [],
|
||||
organList: [],
|
||||
QuestionsList: [],
|
||||
QuestionsForm: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
calculationValue: {
|
||||
get() {
|
||||
return this.questionForm[this.question.Id]
|
||||
},
|
||||
set() {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.question)
|
||||
if (this.question.ClinicalTableQuestionType === 'number') {
|
||||
this.$set(this.questionForm, this.question.Id, 0)
|
||||
} else if (this.question.ClinicalTableQuestionType === 'time') {
|
||||
this.$set(this.questionForm, this.question.Id, null)
|
||||
} else if (this.question.ClinicalTableQuestionType === 'checkbox') {
|
||||
this.$set(this.questionForm, this.question.Id, [])
|
||||
} else{
|
||||
this.$set(this.questionForm, this.question.Id, '')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
},
|
||||
openAddTableCol(row) {
|
||||
this.addOrEdit.visible = true
|
||||
this.addOrEdit.title = row.QuestionName + '表格问题'
|
||||
this.QuestionsList = row.TableQuestions.Questions
|
||||
this.AnswersList = row.TableQuestions.Answers
|
||||
this.questionForm = {}
|
||||
console.log(this.questionForm)
|
||||
},
|
||||
formItemChange(v, question) {
|
||||
},
|
||||
formItemNumberChange(v, question) {
|
||||
this.$emit('formItemTableNumberChange', v, question)
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.my_dialog{
|
||||
.criterion-form-item{
|
||||
>>>.el-form-item__content{
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.criterion-form-item{
|
||||
.el-form-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
>>>.el-form-item__content{
|
||||
width: 500px;
|
||||
}
|
||||
.el-input{
|
||||
width:100%;
|
||||
}
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
>>>.el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 40 40">
|
||||
<path
|
||||
d="M 1.5006714,23.536225 6.8925879,18.994244 14.585721,26.037937 34.019683,4.5410479 38.499329,9.2235032 14.585721,35.458952 z"
|
||||
id="path4"
|
||||
style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1.25402856;stroke-opacity:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 415 B |
|
@ -0,0 +1,380 @@
|
|||
<template>
|
||||
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="globalForm.taskList"
|
||||
>
|
||||
<!-- 访视名称 -->
|
||||
<el-table-column
|
||||
prop="BlindName"
|
||||
:label="$t('trials:globalReview:table:visitName')"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
/>
|
||||
<!-- 评估结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:evaluationRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.evaluationQsList"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否同意访视结果 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:globalReview:table:isAgreeEvaluationRes')"
|
||||
show-overflow-tooltip
|
||||
width="170"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="readingTaskState<2 ">
|
||||
<el-form-item
|
||||
:prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['change','blur']},
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
|
||||
@change="handleAgreeOrNotChange(scope.$index,scope.row.AgreeOrNot[0].GlobalAnswerType)"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingYesOrNo"
|
||||
:key="'AgreeOrNot' + item.value"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1" type="primary">
|
||||
{{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0" type="danger"> {{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
|
||||
<span v-else />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 调整后结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:adjustedRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.adjustedQsList"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs"
|
||||
show-overflow-tooltip
|
||||
:width="index === 3 ? '300' : '150'"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="readingTaskState<2 ">
|
||||
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
|
||||
{{$fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer))}}
|
||||
</span>
|
||||
<el-form-item
|
||||
style="margin-bottom: 0;"
|
||||
v-else
|
||||
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required:parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
|
||||
]"
|
||||
>
|
||||
<label v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
|
||||
<!-- 裁判问题 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0 ">
|
||||
<el-tooltip class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||
<el-option
|
||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<!-- 评估更新类型 GlobalAnswerType:3 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
<el-tooltip class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in globalInfo.assessTypeList"
|
||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && !val.IsBaseLineUse)"
|
||||
:key="val.Code"
|
||||
:label="language === 'en'?val.Value:val.ValueCN"
|
||||
:value="val.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
|
||||
</template>
|
||||
<el-input
|
||||
v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
type="textarea"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
style="width:90%;"
|
||||
:autosize="{ minRows: 2 }"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else-if="scope.row.AfterQuestionList.length>index && scope.row.AfterQuestionList[index].Answer">
|
||||
|
||||
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
|
||||
</span>
|
||||
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode,parseInt(scope.row.AfterQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:globalReview:table:view')"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { batchSubmitGlobalReadingInfo } from '@/api/trials'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
props: {
|
||||
globalInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
globalForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
assessTypes: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
|
||||
},
|
||||
methods: {
|
||||
getText(val, row, type) {
|
||||
var text
|
||||
if (type === 3) {
|
||||
var o = this.globalInfo.assessTypeList.find(v => {
|
||||
return parseInt(v.Code) === parseInt(val)
|
||||
})
|
||||
if (!o) {
|
||||
return ''
|
||||
}
|
||||
return this.language === 'en' ? o.Value : o.ValueCN
|
||||
} else if (row.TypeValue) {
|
||||
return val
|
||||
} else if (row.DictionaryCode){
|
||||
return this.$fd(row.DictionaryCode, parseInt(val))
|
||||
}
|
||||
},
|
||||
handleView(row) {
|
||||
var token = getToken()
|
||||
var visitTaskId = row.VisitTaskId
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
path = `/readingDicoms?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
}
|
||||
const routeData = this.$router.resolve({ path })
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$refs['globalRuleForm'].validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
var answerList = []
|
||||
item.AfterQuestionList.map(i => {
|
||||
var obj = {}
|
||||
if (i.QuestionId) {
|
||||
obj.questionId = i.QuestionId
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.QuestionId}`]
|
||||
} else {
|
||||
obj.questionId = ''
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.GlobalAnswerType}`]
|
||||
}
|
||||
answerList.push(obj)
|
||||
})
|
||||
answerList.push({ questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
|
||||
answer: this.globalForm[ `${index}${item.AgreeOrNot[0].GlobalAnswerType}`] })
|
||||
|
||||
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
|
||||
})
|
||||
var params = {
|
||||
globalTaskId: this.globalInfo.visitTaskId,
|
||||
subjectId: this.globalInfo.subjectId,
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
batchSubmitGlobalReadingInfo(params).then(res => {
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
getBeforeAnswer(qsId, row) {
|
||||
var i = row.BeforeQuestionList.findIndex(item => item.QuestionName === qsId)
|
||||
|
||||
if (i > -1 && row.BeforeQuestionList[i].Answer) {
|
||||
var answer = ''
|
||||
if (row.BeforeQuestionList[i].DictionaryCode) {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
} else {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
}
|
||||
return answer
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
handleAgreeOrNotChange(index, globalAnswerType) {
|
||||
var agreeOrNot = parseInt(this.globalForm[`${index}${globalAnswerType}`])
|
||||
if (agreeOrNot === 1) {
|
||||
var qsList = this.globalForm.taskList[index].AfterQuestionList
|
||||
qsList.map(v => {
|
||||
if (v.QuestionId) {
|
||||
this.globalForm[`${index}${v.QuestionId}`] = ''
|
||||
} else if (v.GlobalAnswerType !== globalAnswerType) {
|
||||
this.globalForm[`${index}${v.GlobalAnswerType}`] = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getAssessType(v) {
|
||||
console.log(this.language)
|
||||
var i = this.globalInfo.assessTypeList.findIndex(i => String(i.Code) === String(v))
|
||||
if (i > -1) {
|
||||
return this.language === 'en' ? this.globalInfo.assessTypeList[i].Value : this.globalInfo.assessTypeList[i].ValueCN
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
>>>.el-form-item label:before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
>>>.el-textarea .el-input__count{
|
||||
background: rgba(0,0,0,0);
|
||||
line-height: normal;
|
||||
}
|
||||
>>>.el-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,245 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<div style="margin-left:auto;">
|
||||
<!-- 提交 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="submitIdArr.length==0"
|
||||
icon="el-icon-check"
|
||||
:loading="loading"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ $t('trials:seletctedReviews:button:submit') }}
|
||||
</el-button>
|
||||
<!-- 下载所有 -->
|
||||
<el-button
|
||||
v-if="hasPermi(['role:pm'])"
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
:disabled="!total"
|
||||
:loading="loading"
|
||||
@click="handleDownloadAll"
|
||||
>
|
||||
{{ $t('trials:seletctedReviews:button:submissionDownAll') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
v-adaptive="{bottomOffset:65}"
|
||||
height="100"
|
||||
:data="list"
|
||||
class="table"
|
||||
:row-class-name="handleHighLighRow"
|
||||
@sort-change="handleSortChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" :selectable="handleSelectTable" />
|
||||
<el-table-column type="index" width="40" />
|
||||
<!-- Name -->
|
||||
<el-table-column
|
||||
prop="LastName"
|
||||
:label="$t('trials:seletctedReviews:table:name')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<router-link
|
||||
style="color: #428bca;"
|
||||
tag="a"
|
||||
:to="{
|
||||
path: `/trialsResume?doctorId=${scope.row.Id}&token=${token}`,
|
||||
}"
|
||||
target="_blank"
|
||||
>{{ scope.row.LastName }} / {{ scope.row.FirstName }}</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- Name CN -->
|
||||
<el-table-column
|
||||
prop="ChineseName"
|
||||
:label="$t('trials:seletctedReviews:table:nameCN')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
/>
|
||||
<!-- ID -->
|
||||
<el-table-column
|
||||
prop="Code"
|
||||
:label="$t('trials:seletctedReviews:table:id')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- Status -->
|
||||
<el-table-column
|
||||
prop="DoctorTrialState"
|
||||
:label="$t('trials:seletctedReviews:table:status')"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.DoctorTrialState === 5" type="primary">{{ $fd('DoctorTrialState', scope.row.DoctorTrialState) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('DoctorTrialState', 16) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- Submitter -->
|
||||
<el-table-column
|
||||
prop="OptUserName"
|
||||
:label="$t('trials:seletctedReviews:table:submitter')"
|
||||
min-width="120"
|
||||
/>
|
||||
<!-- Submission Time -->
|
||||
<el-table-column
|
||||
prop="OptTimeStr"
|
||||
:label="$t('trials:seletctedReviews:table:submissionTime')"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- <el-button type="primary" icon="el-icon-view" @click="handleDetail(scope.row)">Detail</el-button> -->
|
||||
<el-button
|
||||
icon="el-icon-download"
|
||||
circle
|
||||
:title="$t('trials:seletctedReviews:button:submissionDown')"
|
||||
@click="handleDownload(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination class="page" :total="total" :page.sync="listQuery.PageIndex" :limit.sync="listQuery.PageSize" @pagination="getList" />
|
||||
|
||||
<el-dialog
|
||||
:title="$t('trials:seletctedReviews:title:language')"
|
||||
:visible.sync="dialogVisible"
|
||||
width="30%"
|
||||
>
|
||||
<!-- 语言 -->
|
||||
<span>{{ $t('trials:seletctedReviews:label:language') }}: </span>
|
||||
<el-radio-group v-model="language">
|
||||
<el-radio :label="2">English</el-radio>
|
||||
<el-radio :label="1">中文</el-radio>
|
||||
</el-radio-group>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">{{ $t('common:button:cancel') }}</el-button>
|
||||
<el-button type="primary" @click="handleDownloadResumes">{{ $t('common:button:save') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getSubmissionOrApprovalReviewerList, submitReviewer, downloadResume } from '@/api/trials'
|
||||
import store from '@/store'
|
||||
const enrollState = 1
|
||||
export default {
|
||||
name: 'Submission',
|
||||
components: { BaseContainer, Pagination },
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
listQuery: {
|
||||
TrialId: '',
|
||||
IntoGroupSearchState: enrollState,
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
},
|
||||
loading: false,
|
||||
total: 0,
|
||||
listLoading: false,
|
||||
submitIdArr: [],
|
||||
dialogVisible: false,
|
||||
language: 2,
|
||||
token: store.getters.token
|
||||
}
|
||||
},
|
||||
created() { this.initPage() },
|
||||
methods: {
|
||||
initPage() {
|
||||
this.getList()
|
||||
},
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
this.listQuery.TrialId = this.$route.query.trialId
|
||||
getSubmissionOrApprovalReviewerList(this.listQuery).then(res => {
|
||||
this.listLoading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
// eslint-disable-next-line handle-callback-err
|
||||
}).catch(() => { this.listLoading = false })
|
||||
},
|
||||
handleSubmit() {
|
||||
// 是否确认提交?
|
||||
this.$confirm(this.$t('trials:seletctedReviews:message:msg2'), {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.loading = true
|
||||
const trialId = this.$route.query.trialId
|
||||
submitReviewer(trialId, this.submitIdArr, 1).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
// 保存成功
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.$emit('nextStep', 'approval')
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
const arr = []
|
||||
for (let index = 0; index < val.length; index++) {
|
||||
arr.push(val[index].Id)
|
||||
}
|
||||
this.submitIdArr = arr
|
||||
},
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.listQuery.Asc = true
|
||||
} else {
|
||||
this.listQuery.Asc = false
|
||||
}
|
||||
this.listQuery.SortField = column.prop
|
||||
this.listQuery.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleHighLighRow({ row, rowIndex }) {
|
||||
if (row.DoctorTrialState === 5) {
|
||||
return 'selected'
|
||||
}
|
||||
},
|
||||
handleSelectTable(row) { return row.DoctorTrialState !== 5 },
|
||||
handleDetail(row) {
|
||||
const { href } = this.$router.resolve({ path: `/trialsResume?doctorId=${row.Id}` })
|
||||
window.open(href, '_blank')
|
||||
},
|
||||
handleDownloadAll() {
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleDownloadResumes() {
|
||||
this.dialogVisible = false
|
||||
const arr = []
|
||||
for (let index = 0; index < this.list.length; index++) {
|
||||
arr.push(this.list[index].Id)
|
||||
}
|
||||
this.downloadResume(arr)
|
||||
},
|
||||
downloadResume(arr) {
|
||||
downloadResume(this.$route.query.trialId, this.language, arr).then(res => { window.open(res.Result) })
|
||||
},
|
||||
handleDownload(row) { this.downloadResume([row.Id]) }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<div />
|
||||
</template>
|
||||
<script>
|
||||
import { getNextTask, getReadingTool } from '@/api/trials'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
export default {
|
||||
name: 'ReadPage',
|
||||
data() {
|
||||
return {
|
||||
trialId: '',
|
||||
subjectCode: '',
|
||||
subjectId: '',
|
||||
visitTaskId: '',
|
||||
readingCategory: 2,
|
||||
taskBlindName: '',
|
||||
isReadingShowSubjectInfo: false,
|
||||
isReadingShowPreviousResults: false,
|
||||
TrialReadingCriterionId: null,
|
||||
isExistsClinicalData: false,
|
||||
tabName: '',
|
||||
isExistsNoDicomFile: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$router.currentRoute.query.TokenKey) {
|
||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||
changeURLStatic('TokenKey', '')
|
||||
}
|
||||
this.tabName = this.$router.currentRoute.query.tabName ? this.$router.currentRoute.query.tabName : 'read'
|
||||
this.trialId = this.$router.currentRoute.query.trialId
|
||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.subjectId = this.$router.currentRoute.query.subjectId ? this.$router.currentRoute.query.subjectId : ''
|
||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId ? this.$router.currentRoute.query.visitTaskId : ''
|
||||
// this.TrialReadingCriterionId = this.$router.currentRoute.query.trialReadingCriterionId
|
||||
this.TrialReadingCriterionId = localStorage.getItem('TrialReadingCriterionId')
|
||||
// this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults
|
||||
this.getTaskInfo()
|
||||
},
|
||||
methods: {
|
||||
getTaskInfo() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var param = {
|
||||
subjectId: this.subjectId,
|
||||
trialId: this.trialId,
|
||||
visistTaskId: this.visitTaskId,
|
||||
subjectCode: this.subjectCode,
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||
}
|
||||
getNextTask(param).then(async res => {
|
||||
this.readingCategory = res.Result.ReadingCategory
|
||||
this.subjectId = res.Result.SubjectId
|
||||
this.visitTaskId = res.Result.VisitTaskId
|
||||
this.subjectCode = res.Result.SubjectCode
|
||||
this.taskBlindName = res.Result.TaskBlindName
|
||||
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
|
||||
this.isExistsClinicalData = res.Result.IsExistsClinicalData
|
||||
if (this.$router.currentRoute.query.isReadingShowPreviousResults !== undefined && this.$router.currentRoute.query.isReadingShowPreviousResults !== null) {
|
||||
this.isReadingShowPreviousResults = this.$router.currentRoute.query.isReadingShowPreviousResults
|
||||
} else {
|
||||
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
|
||||
}
|
||||
this.isExistsNoDicomFile = res.Result.IsExistsNoDicomFile
|
||||
|
||||
loading.close()
|
||||
if (res.Result.ReadingCategory === 1) {
|
||||
// 访视阅片
|
||||
this.getCriterionConfig()
|
||||
} else if (res.Result.ReadingCategory === 2) {
|
||||
// 全局阅片
|
||||
this.$router.push({
|
||||
path: `/globalReview?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}`
|
||||
})
|
||||
} else if (res.Result.ReadingCategory === 4) {
|
||||
// 裁判阅片
|
||||
this.$router.push({
|
||||
path: `/adReview?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}`
|
||||
})
|
||||
} else if (res.Result.ReadingCategory === 5) {
|
||||
// 肿瘤学阅片
|
||||
this.$router.push({
|
||||
path: `/oncologyReview?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}`
|
||||
})
|
||||
}
|
||||
}).catch(() => { loading.close() })
|
||||
},
|
||||
getCriterionConfig() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
getReadingTool({ visitTaskId: this.visitTaskId }).then(res => {
|
||||
loading.close()
|
||||
if (res.Result.ReadingTool === 0) {
|
||||
window.location.href = `/readingDicoms?TrialReadingCriterionId=${res.Result.TrialReadingCriterionId}&CriterionType=${res.Result.CriterionType}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&tabName=${this.tabName}&isExistsClinicalData=${this.isExistsClinicalData}&isExistsNoDicomFile=${this.isExistsNoDicomFile}`
|
||||
// this.$router.push({
|
||||
// path: `/readingDicoms?TrialReadingCriterionId=${res.Result.TrialReadingCriterionId}&CriterionType=${res.Result.CriterionType}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&tabName=${this.tabName}&isExistsClinicalData=${this.isExistsClinicalData}`
|
||||
// })
|
||||
} else {
|
||||
// if (res.Result.ReadingTool === 1)
|
||||
this.$router.push({
|
||||
path: `/noneDicomReading?trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${this.visitTaskId}&readingCategory=${this.readingCategory}&taskBlindName=${this.taskBlindName}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&isExistsClinicalData=${this.isExistsClinicalData}`
|
||||
})
|
||||
}
|
||||
}).catch(() => { loading.close() })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import createImageIdsAndCacheMetaData from './createImageIdsAndCacheMetaData';
|
||||
import wadoURICreateImageIds from './WADOURICreateImageIds';
|
||||
import initDemo from './initDemo';
|
||||
import setCtTransferFunctionForVolumeActor, {
|
||||
ctVoiRange,
|
||||
} from './setCtTransferFunctionForVolumeActor';
|
||||
import setPetTransferFunctionForVolumeActor from './setPetTransferFunctionForVolumeActor';
|
||||
import setPetColorMapTransferFunctionForVolumeActor from './setPetColorMapTransferFunctionForVolumeActor';
|
||||
import setTitleAndDescription from './setTitleAndDescription';
|
||||
import addButtonToToolbar from './addButtonToToolbar';
|
||||
import addCheckboxToToolbar from './addCheckboxToToolbar';
|
||||
import addToggleButtonToToolbar from './addToggleButtonToToolbar';
|
||||
import addDropdownToToolbar from './addDropdownToToolbar';
|
||||
import addSliderToToolbar from './addSliderToToolbar';
|
||||
import camera from './camera';
|
||||
|
||||
export {
|
||||
createImageIdsAndCacheMetaData,
|
||||
wadoURICreateImageIds,
|
||||
initDemo,
|
||||
setTitleAndDescription,
|
||||
addButtonToToolbar,
|
||||
addCheckboxToToolbar,
|
||||
addDropdownToToolbar,
|
||||
addSliderToToolbar,
|
||||
addToggleButtonToToolbar,
|
||||
setPetColorMapTransferFunctionForVolumeActor,
|
||||
setPetTransferFunctionForVolumeActor,
|
||||
setCtTransferFunctionForVolumeActor,
|
||||
ctVoiRange,
|
||||
camera,
|
||||
};
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,48 @@
|
|||
<template>
|
||||
<div class="comment-info">
|
||||
<el-form :model="statusList" class="demo-form-inline" size="small">
|
||||
<el-form-item label="Comment:">
|
||||
<el-input
|
||||
v-model="statusList.AdminComment"
|
||||
type="textarea"
|
||||
autosize
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
statusList: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.comment-info{
|
||||
padding:5px 15px;
|
||||
font-size:13px;
|
||||
.el-form-item--mini.el-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.el-form-item--small.el-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.el-form-item__content{
|
||||
font-size: 13px;
|
||||
}
|
||||
.el-form-item__label{
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,434 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<el-tabs v-model="TrialReadingCriterionId" type="border-card">
|
||||
<el-tab-pane v-for="i of trialCriterionList" :key="i.TrialReadingCriterionId" :label="i.TrialReadingCriterionName" :name="i.TrialReadingCriterionId">
|
||||
<div v-if="TrialReadingCriterionId === i.TrialReadingCriterionId">
|
||||
<div slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="是否加急"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.IsUrgent"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="'IsUrgent' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item label="受试者编号">
|
||||
<el-input
|
||||
v-model="searchData.SubjectCode"
|
||||
style="width:130px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 盲态访视名称 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="盲态访视名称"
|
||||
>
|
||||
<el-input
|
||||
v-model="searchData.TaskBlindName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 任务类型 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="任务类型"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.ReadingCategory"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.ReadingCategory"
|
||||
:key="'ReadingCategory' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 审核状态 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="审核状态"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.AuditState"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.MedicalReviewAuditState"
|
||||
:key="'AuditState' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 医学审核建议 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="医学审核建议"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.AuditAdviceEnum"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.AuditAdvice"
|
||||
:key="'AuditAdvice' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 是否认可 -->
|
||||
<el-form-item
|
||||
style="margin-bottom:10px"
|
||||
label="是否认可"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.DoctorUserIdeaEnum"
|
||||
clearable
|
||||
style="width:120px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.MedicalReviewDoctorUserIdea"
|
||||
:key="'MedicalReviewDoctorUserIdea' + item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:75}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
>
|
||||
<el-table-column type="index" width="40" align="left" />
|
||||
<!-- 是否加急 -->
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
min-width="100"
|
||||
label="是否加急"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 受试者编号 -->
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
min-width="100"
|
||||
label="受试者编号"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
|
||||
<!-- 盲态访视名称 -->
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
min-width="100"
|
||||
label="盲态访视名称"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TrialReadingCriterionName"
|
||||
label="阅片标准"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
label="任务类型"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">
|
||||
{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 任务状态 -->
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="阅片任务状态"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="AuditState"
|
||||
label="审核状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.AuditState === 0" type="warning">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.AuditState === 1" type="primary">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
<el-tag v-if="scope.row.AuditState === 2" type="danger">
|
||||
{{ $fd('MedicalReviewAuditState', scope.row.AuditState) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 首次质询时间 -->
|
||||
<el-table-column
|
||||
prop="FirstReplyTime"
|
||||
min-width="100"
|
||||
label="首次质询时间"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 最近回复时间 -->
|
||||
<el-table-column
|
||||
prop="LastReplyTime"
|
||||
min-width="100"
|
||||
label="最近回复时间"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 医学审核建议 -->
|
||||
<el-table-column
|
||||
prop="AuditAdviceEnum"
|
||||
label="医学审核建议"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('AuditAdvice',scope.row.AuditAdviceEnum) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否认可 -->
|
||||
<el-table-column
|
||||
prop="DoctorUserIdeaEnum"
|
||||
min-width="100"
|
||||
label="是否认可"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('MedicalReviewDoctorUserIdea',scope.row.DoctorUserIdeaEnum) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="200"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 阅片 -->
|
||||
<el-button
|
||||
:disabled="!scope.row.IsHaveQuestion || scope.row.IsInvalid"
|
||||
circle
|
||||
title="查看"
|
||||
icon="el-icon-edit-outline"
|
||||
@click="handleReadMecialAudit(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="!scope.row.IsHaveQuestion || scope.row.IsInvalid"
|
||||
circle
|
||||
title="回复"
|
||||
icon="el-icon-chat-dot-round"
|
||||
@click="handleReply(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-dialog
|
||||
v-if="chatForm.visible"
|
||||
:visible.sync="chatForm.visible"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="chatForm.title"
|
||||
width="600px"
|
||||
>
|
||||
<ChatForm
|
||||
:task-medical-review-id="currentRow.Id"
|
||||
:visit-task-id="currentRow.VisitTaskId"
|
||||
@getList="getList"
|
||||
@close="chatForm.visible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 审核 -->
|
||||
<el-dialog
|
||||
v-if="auditVisible"
|
||||
:visible.sync="auditVisible"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="true"
|
||||
title="医学审核详情"
|
||||
>
|
||||
<MedicalAudit
|
||||
:task-medical-review-id="currentRow.Id"
|
||||
:visit-task-id="currentRow.VisitTaskId"
|
||||
:row-data="currentRow"
|
||||
@getList="getList"
|
||||
@close="auditVisible=false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getIRMedicalFeedbackList } from '@/api/trials'
|
||||
import { getTrialCriterionList } from '@/api/trials/reading'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import ChatForm from './components/ChatForm'
|
||||
import MedicalAudit from '@/views/trials/trials-panel/reading/mim-medical-audit/components/MedicalAudit'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
IsUrgent: null,
|
||||
SubjectCode: '',
|
||||
TaskBlindName: '',
|
||||
ReadingCategory: null,
|
||||
AuditState: null,
|
||||
AuditAdviceEnum: null,
|
||||
DoctorUserIdeaEnum: null,
|
||||
PageIndex: 1,
|
||||
PageSize: 20
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'ReadTask',
|
||||
components: { BaseContainer, Pagination, ChatForm, MedicalAudit },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
trialId: '',
|
||||
currentRow: {},
|
||||
chatForm: { visible: false, title: '质询记录' },
|
||||
auditVisible: false,
|
||||
trialCriterionList: [],
|
||||
TrialReadingCriterionId: '0'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
TrialReadingCriterionId(v) {
|
||||
if (v) {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getTrialCriterionList()
|
||||
},
|
||||
methods: {
|
||||
getTrialCriterionList() {
|
||||
getTrialCriterionList(this.trialId).then(res => {
|
||||
this.trialCriterionList = res.Result
|
||||
this.TrialReadingCriterionId = this.trialCriterionList[0].TrialReadingCriterionId
|
||||
}).catch(() => {})
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId
|
||||
getIRMedicalFeedbackList(this.searchData).then(res => {
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
handleReadMecialAudit(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.auditVisible = true
|
||||
},
|
||||
handleReply(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.chatForm.visible = true
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,111 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
import dcmjs from 'dcmjs'
|
||||
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv'
|
||||
import { getPTImageIdInstanceMetadata } from './getPTImageIdInstanceMetadata'
|
||||
import { utilities } from '@cornerstonejs/core'
|
||||
// import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
|
||||
import ptScalingMetaDataProvider from './ptScalingMetaDataProvider'
|
||||
import getPixelSpacingInformation from './getPixelSpacingInformation'
|
||||
import { convertMultiframeImageIds, prefetchMetadataInformation } from './convertMultiframeImageIds'
|
||||
import removeInvalidTags from './removeInvalidTags'
|
||||
const { calibratedPixelSpacingMetadataProvider } = utilities
|
||||
function parseImageId(imageId) {
|
||||
// build a url by parsing out the url scheme and frame index from the imageId
|
||||
const firstColonIndex = imageId.indexOf(':')
|
||||
|
||||
let url = imageId.substring(firstColonIndex + 1)
|
||||
const frameIndex = url.indexOf('frame=')
|
||||
|
||||
let frame
|
||||
|
||||
if (frameIndex !== -1) {
|
||||
const frameStr = url.substr(frameIndex + 6)
|
||||
|
||||
frame = parseInt(frameStr, 10)
|
||||
url = url.substr(0, frameIndex - 1)
|
||||
}
|
||||
|
||||
return {
|
||||
scheme: imageId.substr(0, firstColonIndex),
|
||||
url,
|
||||
frame
|
||||
}
|
||||
}
|
||||
async function createImageIdsAndCacheMetaData({
|
||||
modality,
|
||||
imageIds
|
||||
}) {
|
||||
await prefetchMetadataInformation(imageIds)
|
||||
imageIds = convertMultiframeImageIds(imageIds)
|
||||
imageIds.forEach((imageId) => {
|
||||
const parseImage = parseImageId(imageId)
|
||||
const imageData =
|
||||
cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.get(parseImage.url)
|
||||
const arrayBuffer = imageData.byteArray.buffer
|
||||
var dicomData = dcmjs.data.DicomMessage.readFile(arrayBuffer)
|
||||
var dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(
|
||||
dicomData.dict
|
||||
)
|
||||
dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(
|
||||
dicomData.meta
|
||||
)
|
||||
var instanceMetaData = dataset
|
||||
instanceMetaData = removeInvalidTags(instanceMetaData)
|
||||
if (instanceMetaData) {
|
||||
const pixelSpacing = getPixelSpacingInformation(instanceMetaData)
|
||||
if (pixelSpacing) {
|
||||
calibratedPixelSpacingMetadataProvider.add(
|
||||
imageId,
|
||||
// pixelSpacing.map((s) => parseFloat(s))
|
||||
{ rowPixelSpacing: parseFloat(pixelSpacing[0]),
|
||||
columnPixelSpacing: parseFloat(pixelSpacing[1])
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
if (modality === 'PT') {
|
||||
const InstanceMetadataArray = []
|
||||
imageIds.forEach((imageId) => {
|
||||
// var parseImage = parseImageId(imageId)
|
||||
// imageId,
|
||||
const instanceMetadata = getPTImageIdInstanceMetadata(imageId)
|
||||
if (typeof instanceMetadata.CorrectedImage === 'string') {
|
||||
instanceMetadata.CorrectedImage =
|
||||
instanceMetadata.CorrectedImage.split('\\')
|
||||
}
|
||||
|
||||
if (instanceMetadata) {
|
||||
InstanceMetadataArray.push(instanceMetadata)
|
||||
}
|
||||
})
|
||||
if (InstanceMetadataArray.length) {
|
||||
// const suvScalingFactors = calculateSUVScalingFactors(
|
||||
// InstanceMetadataArray
|
||||
// )
|
||||
// InstanceMetadataArray.forEach((instanceMetadata, index) => {
|
||||
// ptScalingMetaDataProvider.addInstance(
|
||||
// imageIds[index],
|
||||
// suvScalingFactors[index]
|
||||
// )
|
||||
// })
|
||||
try {
|
||||
const suvScalingFactors = calculateSUVScalingFactors(
|
||||
InstanceMetadataArray
|
||||
)
|
||||
InstanceMetadataArray.forEach((instanceMetadata, index) => {
|
||||
ptScalingMetaDataProvider.addInstance(
|
||||
imageIds[index],
|
||||
suvScalingFactors[index]
|
||||
)
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
return imageIds
|
||||
}
|
||||
|
||||
export { createImageIdsAndCacheMetaData }
|
|
@ -0,0 +1,269 @@
|
|||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}" style="position: relative">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}" style="padding-bottom: 50px;overflow-y: auto;">
|
||||
<h3 style="color: #ddd;padding: 5px 0px;margin: 0;" v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ taskBlindName }}</span>
|
||||
</h3>
|
||||
<QuestionsPreview
|
||||
ref="QuestionsPreview"
|
||||
v-if="ecrfShow"
|
||||
:visitTaskId="visitTaskId"
|
||||
:criterionId="TrialReadingCriterionId">
|
||||
</QuestionsPreview>
|
||||
</div>
|
||||
<div style="position: absolute;bottom:0;left: 0;z-index: 10;background: #000;width: 100%;display: flex;justify-content: right;align-items: center;height: 50px">
|
||||
<el-button size="mini" v-if="readingTaskState<2" style="margin-right: 10px" @click="handleSave(true)">
|
||||
保存
|
||||
</el-button>
|
||||
<el-button size="mini" style="margin-right: 10px" v-if="readingTaskState<2 && IseCRFShowInDicomReading" @click="handleConfirm">提交</el-button>
|
||||
</div>
|
||||
<!-- 签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { submitDicomVisitTask } from '@/api/trials'
|
||||
import DicomEvent from '../components/DicomEvent'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import QuestionsPreview from './CustomizeQuestionsPreview'
|
||||
import const_ from '@/const/sign-code'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'CustomizeMeasurementList',
|
||||
components: {
|
||||
QuestionsPreview, SignForm
|
||||
},
|
||||
props: {
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
IseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
height: window.innerHeight - 140,
|
||||
visitTaskId: '',
|
||||
loading: false,
|
||||
CriterionType: null,
|
||||
subjectCode: '',
|
||||
taskBlindName: '',
|
||||
TrialReadingCriterionId: null,
|
||||
ecrfShow: false,
|
||||
signCode: null,
|
||||
signVisible: false,
|
||||
readingTaskState: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList'])
|
||||
},
|
||||
mounted() {
|
||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
DicomEvent.$on('loadMeasurementList', async obj => {
|
||||
console.log(11111, this.$refs['QuestionsPreview'])
|
||||
if (this.visitTaskId !== obj.visitTaskId) {
|
||||
this.visitTaskId = obj.visitTaskId
|
||||
this.taskBlindName = obj.taskBlindName
|
||||
this.$refs['QuestionsPreview'].getCustomTableQuestionAnswer(obj.visitTaskId)
|
||||
}
|
||||
})
|
||||
DicomEvent.$on('getCustomTableQuestionAnswer', (visitTaskId) => {
|
||||
this.$refs['QuestionsPreview'].getCustomTableQuestionAnswer(visitTaskId)
|
||||
})
|
||||
DicomEvent.$on('setCollapseActive', measureData => {
|
||||
})
|
||||
DicomEvent.$on('changeLesionType', (questionsObj) => {
|
||||
})
|
||||
DicomEvent.$on('getAllUnSaveLesions', (callback) => {
|
||||
})
|
||||
|
||||
DicomEvent.$on('split', measureData => {
|
||||
})
|
||||
DicomEvent.$on('setReadingState', readingTaskState => {
|
||||
this.readingTaskState = readingTaskState
|
||||
console.log(this.readingTaskState)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('loadMeasurementList')
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
DicomEvent.$off('changeLesionType')
|
||||
DicomEvent.$off('getUnSaveTarget')
|
||||
DicomEvent.$off('setReadingState')
|
||||
DicomEvent.$off('getCustomTableQuestionAnswer')
|
||||
},
|
||||
methods: {
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.visitTaskId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
this.signVisible = false
|
||||
submitDicomVisitTask(params).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
try {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
if (this.$refs['signForm']) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
this.signVisible = false
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
|
||||
DicomEvent.$emit('setReadingState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
this.$confirm('当前阅片任务已完成,是否进入下一个阅片任务?', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
try {DicomEvent.$emit('getNextTask')} catch (e) {console.log(e)}
|
||||
})
|
||||
.catch(action => {
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
async handleConfirm() {
|
||||
var res = await this.$refs['QuestionsPreview'].handleSave(false)
|
||||
if (res) {
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
}
|
||||
},
|
||||
handleSave(isMsg) {
|
||||
this.$refs['QuestionsPreview'].handleSave(isMsg)
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
initPage(obj) {
|
||||
if (this.visitTaskId !== obj.visitTaskId) {
|
||||
this.visitTaskId = obj.visitTaskId
|
||||
this.taskBlindName = obj.taskBlindName
|
||||
this.activeName = ''
|
||||
this.ecrfShow = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
.container{
|
||||
padding: 10px;
|
||||
}
|
||||
.title{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
.add-icon{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
border: 1px solid #938b8b;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #424242;
|
||||
|
||||
}
|
||||
.lesion_list{
|
||||
position: relative;
|
||||
}
|
||||
.el-collapse{
|
||||
border-bottom:none;
|
||||
>>>.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
>>>.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
padding-left: 5px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
>>>.el-collapse-item__wrap{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
}
|
||||
>>>.el-collapse-item__content{
|
||||
width:260px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
// border: 1px solid #ffeb3b;
|
||||
border: 1px solid #fff;
|
||||
z-index: 1;
|
||||
color: #ddd;
|
||||
padding: 5px;
|
||||
background-color:#1e1e1e;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,318 @@
|
|||
<template>
|
||||
<box-content style="height: 100%;background: #fff;">
|
||||
<!-- 搜索框 -->
|
||||
<div class="search">
|
||||
<el-form :inline="true" class="base-search-form">
|
||||
<!-- 文件类型 -->
|
||||
<el-form-item :label="$t('trials:attachment:table:fileType')">
|
||||
<el-select
|
||||
v-model="searchData.FileTypeId"
|
||||
style="width:150px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Trial_Document"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 文件名称 -->
|
||||
<el-form-item :label="$t('trials:attachment:table:fileName')">
|
||||
<el-input v-model="searchData.Name" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto;">
|
||||
<!-- 新增 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:attachment:add']"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:add') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 系统文件列表 -->
|
||||
<el-table
|
||||
ref="attachmentList"
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column type="index" width="40" />
|
||||
<!-- 文件类型 -->
|
||||
<el-table-column
|
||||
prop="FileType"
|
||||
:label="$t('trials:attachment:table:fileType')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
/>
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column
|
||||
prop="Name"
|
||||
:label="$t('trials:attachment:table:fileName')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
/>
|
||||
<!-- 查看最短时间(分钟) -->
|
||||
<el-table-column
|
||||
prop="SignViewMinimumMinutes"
|
||||
:label="$t('trials:attachment:table:min')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="170"
|
||||
/>
|
||||
<!-- 是否废除 -->
|
||||
<el-table-column
|
||||
prop="IsDeleted"
|
||||
:label="$t('trials:attachment:table:isDeleted')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 需要签署的用户类型 -->
|
||||
<el-table-column
|
||||
prop="NeedConfirmedUserTypes"
|
||||
:label="$t('trials:attachment:table:userType')"
|
||||
show-overflow-tooltip
|
||||
min-width="160"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.NeedConfirmedUserTypes?scope.row.NeedConfirmedUserTypes.join(', '):'' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 描述 -->
|
||||
<el-table-column
|
||||
prop="Description"
|
||||
:label="$t('trials:attachment:table:description')"
|
||||
show-overflow-tooltip
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- 更新时间 -->
|
||||
<el-table-column
|
||||
prop="UpdateTime"
|
||||
:label="$t('trials:attachment:table:updateTime')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="150"
|
||||
/>
|
||||
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="400"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
:title="$t('trials:attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)"
|
||||
/>
|
||||
<!-- 编辑 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:attachment:edit']"
|
||||
circle
|
||||
:title="$t('trials:attachment:action:edit')"
|
||||
icon="el-icon-edit-outline"
|
||||
:disabled="scope.row.IsSomeUserSigned || scope.row.IsDeleted"
|
||||
@click="handleEdit(scope.row)"
|
||||
/>
|
||||
<!-- 废除 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:attachment:abolish']"
|
||||
:disabled="scope.row.IsDeleted"
|
||||
circle
|
||||
:title="$t('trials:attachment:action:apolish')"
|
||||
icon="el-icon-delete"
|
||||
@click="handleRepeal(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
|
||||
<!-- 新增/编辑 -->
|
||||
<el-dialog
|
||||
v-if="editVisible"
|
||||
:visible.sync="editVisible"
|
||||
:close-on-click-modal="false"
|
||||
:title="title"
|
||||
width="800px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<AttachmentForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 预览文件 -->
|
||||
<el-dialog
|
||||
v-if="previewVisible"
|
||||
:visible.sync="previewVisible"
|
||||
:title="$t('trials:attachment:dialogTitle:preview')"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div class="base-modal-body" style="border:2px solid #ccc;padding: 10px">
|
||||
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" />
|
||||
</div>
|
||||
|
||||
</el-dialog>
|
||||
</box-content>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { getTrialDocumentList, userAbandonDoc } from '@/api/trials'
|
||||
import BoxContent from '@/components/BoxContent'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import AttachmentForm from './components/attachmentForm'
|
||||
import PreviewFile from './components/previewFile'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
FileTypeId: '',
|
||||
Name: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
SortField: '',
|
||||
Asc: false
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialAttachmentList',
|
||||
components: { BoxContent, Pagination, AttachmentForm, PreviewFile },
|
||||
dicts: ['Trial_Document'],
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
loading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
editVisible: false,
|
||||
previewVisible: false,
|
||||
title: '',
|
||||
currentRow: {},
|
||||
currentPath: '',
|
||||
currentType: '',
|
||||
trialId: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取系统文件数据
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
getTrialDocumentList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
const { CurrentPageData, TotalCount } = res.Result
|
||||
CurrentPageData.forEach(item => {
|
||||
item.NeedConfirmedUserTypes = []
|
||||
item.NeedConfirmedUserTypeeIds = []
|
||||
item.NeedConfirmedUserTypeList.forEach((i) => {
|
||||
item.NeedConfirmedUserTypes.push(i.UserTypeShortName)
|
||||
item.NeedConfirmedUserTypeeIds.push(i.NeedConfirmUserTypeId)
|
||||
})
|
||||
})
|
||||
this.list = CurrentPageData
|
||||
this.total = TotalCount
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 新增
|
||||
handleAdd() {
|
||||
this.title = this.$t('common:button:add')
|
||||
this.currentRow = {}
|
||||
this.editVisible = true
|
||||
},
|
||||
// 预览
|
||||
handlePreview(row) {
|
||||
const { Name, FullFilePath } = row
|
||||
this.currentPath = FullFilePath
|
||||
this.currentType = row.Name ? Name.substring(Name.lastIndexOf('.') + 1).toLocaleLowerCase() : ''
|
||||
this.previewVisible = true
|
||||
},
|
||||
// 编辑
|
||||
handleEdit(row) {
|
||||
this.title = this.$t('common:button:edit')
|
||||
this.currentRow = { ...row }
|
||||
this.editVisible = true
|
||||
},
|
||||
// 废除
|
||||
handleRepeal(row) {
|
||||
this.$confirm(this.$t('trials:attachment:message:abolish'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = true
|
||||
userAbandonDoc(row.Id, false)
|
||||
.then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
this.$message.success(this.$t('trials:trials-list:message:abolitionSuccessfully'))
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 关闭编辑弹窗
|
||||
closeDialog() {
|
||||
this.editVisible = false
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
this.$nextTick(() => {
|
||||
this.$refs.attachmentList.clearSort()
|
||||
})
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,808 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="study-wrapper">
|
||||
<h4 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;text-align: center;background-color: #4c4c4c;">
|
||||
{{ subjectCode }}
|
||||
</h4>
|
||||
<h4 v-if="isReadingShowSubjectInfo" style="color: #ddd;padding: 5px 0px;margin: 0;text-align: center;background-color: #4c4c4c;margin-bottom: 5px;">
|
||||
{{ taskBlindName }}
|
||||
</h4>
|
||||
<div class="ps">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
<template slot="title">
|
||||
<div v-if="study.IsCriticalSequence" class="dicom-desc">
|
||||
<!-- 关键序列 -->
|
||||
{{ $t('trials:reading:title:keySeries') }}
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="dicom-desc"
|
||||
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
|
||||
>
|
||||
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
|
||||
<div>
|
||||
<span>{{ study.StudyCode }} {{ study.Description }}</span>
|
||||
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<div class="series">
|
||||
<div
|
||||
v-for="(series, i) in study.SeriesList"
|
||||
:key="i"
|
||||
style="position:relative;margin:10px 0px;"
|
||||
series-type="current"
|
||||
@click="showSeriesImage(index,i,series)"
|
||||
>
|
||||
|
||||
<div
|
||||
:class="{'series-active': i==seriesIndex && index === studyIndex}"
|
||||
class="series-wrapper"
|
||||
>
|
||||
<el-image
|
||||
class="image-preview"
|
||||
:src="series.previewImageUrl"
|
||||
fit="fill"
|
||||
/>
|
||||
<div class="image-desc">
|
||||
<div class="flex-div">
|
||||
<div>#{{ series.seriesNumber }} </div>
|
||||
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount">
|
||||
<!-- 下载 -->
|
||||
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
|
||||
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
|
||||
</el-tooltip>
|
||||
<!-- 暂停 -->
|
||||
<el-tooltip v-else class="item" effect="dark" :content="$t('trials:reading:button:pause')" placement="bottom">
|
||||
<i class="el-icon-video-pause" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="stopLoadSeries(series,index,i)" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-tooltip v-else-if="series.prefetchInstanceCount === 0" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
|
||||
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<p v-show="series.description">
|
||||
<el-tooltip class="item" effect="dark" :content="series.description" placement="right">
|
||||
<div style="">{{ series.description }}</div>
|
||||
</el-tooltip>
|
||||
</p>
|
||||
|
||||
<p v-show="series.sliceThickness">
|
||||
T: {{ series.sliceThickness }}
|
||||
</p>
|
||||
<p v-show="series.instanceCount">
|
||||
{{ series.modality }}: {{ series.instanceCount }} image
|
||||
</p>
|
||||
|
||||
<div class="flex-div">
|
||||
<div v-if="measureData.findIndex(v=>v.SeriesId === series.seriesId) > -1">
|
||||
<!-- 有标注 -->
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:marked')" placement="right">
|
||||
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
|
||||
</el-tooltip>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" style="width: 100%;">
|
||||
<el-progress
|
||||
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as dicomParser from 'dicom-parser'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import DicomEvent from './DicomEvent'
|
||||
import { mapGetters } from 'vuex'
|
||||
import store from '@/store'
|
||||
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
|
||||
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
|
||||
// const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
|
||||
export default {
|
||||
name: 'StudyList',
|
||||
props: {
|
||||
trialId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
subjectVisitId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isReading: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
taskBlindName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
studyList: [],
|
||||
cachedImages: [],
|
||||
studyIndex: null,
|
||||
seriesIndex: null,
|
||||
loading: false,
|
||||
measureData: [],
|
||||
isRender: false,
|
||||
subjectCode: '',
|
||||
activeNames: [],
|
||||
seriesArr: [],
|
||||
imageList: [],
|
||||
loopLoadStatus: 0 // -1暂停下载 0未下载完成 1下载完成
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'currentTaskId', 'activeSeries'])
|
||||
},
|
||||
watch: {
|
||||
visitTaskList: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx === -1) return
|
||||
this.measureData = this.visitTaskList[idx].MeasureData
|
||||
}
|
||||
}
|
||||
// activeSeries: {
|
||||
// immediate: true,
|
||||
// handler(val) {
|
||||
// console.log('activeSeries', val)
|
||||
// this.studyIndex = val.studyIndex
|
||||
// this.seriesIndex = val.seriesIndex
|
||||
// }
|
||||
// }
|
||||
},
|
||||
mounted() {
|
||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
// DicomEvent.$on('getMeasureData', () => {
|
||||
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
// this.measureData = this.visitTaskList[idx].MeasureData
|
||||
// })
|
||||
|
||||
// DicomEvent.$on('setReadingState', readingTaskState => {
|
||||
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
// if (idx > -1) {
|
||||
// this.studyList = this.visitTaskList[idx].StudyList
|
||||
// }
|
||||
// })
|
||||
|
||||
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
||||
},
|
||||
beforeDestroy() {
|
||||
cornerstone.imageCache.purgeCache()
|
||||
// DicomEvent.$off('getMeasureData')
|
||||
},
|
||||
methods: {
|
||||
initStudyInfo() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
// 初始化待渲染序列
|
||||
this.getInitSeries().then((res) => {
|
||||
requestPoolManager.startTaskTimer()
|
||||
res.map((item) => {
|
||||
this.loadInitialImage(item)
|
||||
})
|
||||
var i = res.findIndex(s => s.isCurrentTask)
|
||||
if (i > -1) {
|
||||
var p = this.visitTaskId === this.currentTaskId ? parseInt(new Date().getTime()) : 999 // 非当前任务,符合自动下载的权重次之
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
this.measureData = this.visitTaskList[idx].MeasureData
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
|
||||
this.studyList.map((study, studyIndex) => {
|
||||
study.SeriesList.map((series, seriesIndex) => {
|
||||
var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
|
||||
if (sliceThickness === 5 || series.instanceCount <= 100) {
|
||||
series.imageIds.map(image => {
|
||||
let priority = 0
|
||||
if (series.seriesId === res[i].seriesId) {
|
||||
priority = parseInt(new Date().getTime()) * 10
|
||||
} else {
|
||||
priority = --p
|
||||
}
|
||||
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
this.loopLoad()
|
||||
}
|
||||
}
|
||||
DicomEvent.$emit('loadImageStacks', res)
|
||||
loading.close()
|
||||
this.isRender = true
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
// 获取初始化序列信息
|
||||
loadInitialImage(seriesInfo) {
|
||||
var p = parseInt(new Date().getTime())
|
||||
var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex]
|
||||
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => {
|
||||
this.imageLoaded(seriesInfo, res.data.string('x0020000e'))
|
||||
})
|
||||
},
|
||||
getStudyList() {
|
||||
if (!this.isRender) {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
|
||||
this.measureData = this.visitTaskList[idx].MeasureData
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
var sIdx = this.studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
this.studyIndex = sIdx
|
||||
this.seriesIndex = 0
|
||||
this.activeNames = [`${this.studyList[sIdx].StudyId}`]
|
||||
|
||||
this.loadImages(this.visitTaskList[idx])
|
||||
}
|
||||
}
|
||||
this.isRender = true
|
||||
}
|
||||
},
|
||||
|
||||
async getInitSeries() {
|
||||
var seriesList = []
|
||||
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
if (this.visitTaskList[idx].IsBaseLineTask || !isReadingTaskViewInOrder) {
|
||||
// 基线
|
||||
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
|
||||
if (Object.keys(obj).length !== 0) {
|
||||
this.studyIndex = obj.studyIndex
|
||||
this.seriesIndex = obj.seriesIndex
|
||||
seriesList.push(obj.series)
|
||||
this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`]
|
||||
this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true
|
||||
} else {
|
||||
// 初始化问题表单
|
||||
if (this.studyList.length > 0) {
|
||||
this.activeNames = [`${this.studyList[0].StudyId}`]
|
||||
}
|
||||
|
||||
// DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName })
|
||||
}
|
||||
} else {
|
||||
// 随访
|
||||
var bsIdx = null
|
||||
var criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
if (criterionType === 10) {
|
||||
const i = this.visitTaskList.findIndex(i => i.IsCurrentTask)
|
||||
|
||||
bsIdx = i - 1
|
||||
} else {
|
||||
bsIdx = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
|
||||
}
|
||||
|
||||
if (bsIdx > -1) {
|
||||
var trialId = this.$router.currentRoute.query.trialId
|
||||
await store.dispatch('reading/getMeasuredData', this.visitTaskList[bsIdx].VisitTaskId)
|
||||
await store.dispatch('reading/getStudyInfo', { trialId: trialId, subjectVisitId: this.visitTaskList[bsIdx].VisitId, visitTaskId: this.visitTaskList[bsIdx].VisitTaskId, taskBlindName: this.visitTaskList[bsIdx].TaskBlindName })
|
||||
|
||||
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
|
||||
seriesList.push(firstObj.series)
|
||||
const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] })
|
||||
this.studyIndex = secondObj.studyIndex
|
||||
this.seriesIndex = secondObj.seriesIndex
|
||||
seriesList.push(secondObj.series)
|
||||
this.studyList[ secondObj.studyIndex].SeriesList[secondObj.seriesIndex].isFirstRender = true
|
||||
this.studyIndex = secondObj.studyIndex
|
||||
this.seriesIndex = secondObj.seriesIndex
|
||||
|
||||
this.activeNames = [`${this.studyList[secondObj.studyIndex].StudyId}`]
|
||||
} else {
|
||||
const sIdx = this.studyList.findIndex(s => s.IsDicom)
|
||||
const series = this.studyList[sIdx].SeriesList[0]
|
||||
series.imageIdIndex = Math.floor(series.imageIds.length / 2)
|
||||
seriesList.push(series)
|
||||
this.studyIndex = sIdx
|
||||
this.seriesIndex = 0
|
||||
|
||||
this.activeNames = [`${this.studyList[sIdx].StudyId}`]
|
||||
}
|
||||
}
|
||||
|
||||
return seriesList
|
||||
},
|
||||
getSecondMarkedSeries(baseObj, visitTaskInfo) {
|
||||
var obj = {}
|
||||
var studyList = visitTaskInfo.StudyList
|
||||
var measureDatas = visitTaskInfo.MeasureData
|
||||
if (baseObj.isMarked) {
|
||||
var i = measureDatas.findIndex(i => Object.keys(i.MeasureData).length > 0 && i.OrderMarkName === baseObj.measureData.OrderMarkName)
|
||||
if (i !== -1) {
|
||||
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId)
|
||||
const seriesList = studyList[sdIndx].SeriesList
|
||||
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
|
||||
// const instanceList = seriesList[srIdx].imageIds
|
||||
const instanceList = seriesList[srIdx].instanceList
|
||||
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId))
|
||||
const series = seriesList[srIdx]
|
||||
series.imageIdIndex = isIdx
|
||||
|
||||
obj.studyIndex = sdIndx
|
||||
obj.seriesIndex = srIdx
|
||||
obj.series = series
|
||||
obj.seriesId = series.seriesId
|
||||
return obj
|
||||
}
|
||||
}
|
||||
var seriesInfo = null
|
||||
var seriesList = studyList.map(s => s.SeriesList).flat()
|
||||
var similarArr = seriesList.map((i, index) => {
|
||||
return { similar: this.strSimilarity2Percent(i.description, baseObj.series.description), index }
|
||||
})
|
||||
similarArr = similarArr.sort((a, b) => {
|
||||
return b.similar - a.similar
|
||||
})
|
||||
var idx = similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
|
||||
if (idx > -1) {
|
||||
seriesInfo = seriesList[idx]
|
||||
}
|
||||
|
||||
// const idx = seriesList.findIndex(series => series.description === baseSeries.description)
|
||||
// idx > -1 ? obj = seriesList[idx] : ''
|
||||
if (!seriesInfo) {
|
||||
// 描述不一致,则筛选层厚一致
|
||||
const idx = seriesList.findIndex(series => series.sliceThickness === baseObj.series.sliceThickness)
|
||||
idx > -1 ? seriesInfo = seriesList[idx] : ''
|
||||
}
|
||||
if (!seriesInfo) {
|
||||
// 层厚不一致,则筛选图像数量一致
|
||||
const idx = seriesList.findIndex(series => series.instanceCount === baseObj.series.instanceCount)
|
||||
idx > -1 ? seriesInfo = seriesList[idx] : ''
|
||||
}
|
||||
if (!seriesInfo) {
|
||||
// 都不符合要求, 判断是否存在层厚为5的序列,否则显示第一个检查的第一个序列
|
||||
const idx = seriesList.findIndex(series => series.isDicom && parseInt(series.instanceCount) === 5)
|
||||
idx > -1 ? seriesInfo = seriesList[idx] : seriesInfo = seriesList[0]
|
||||
}
|
||||
if (seriesInfo) {
|
||||
seriesInfo.imageIdIndex = Math.floor(seriesInfo.imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
|
||||
obj.studyIndex = seriesInfo.studyIndex
|
||||
obj.seriesIndex = seriesInfo.seriesIndex
|
||||
obj.series = seriesInfo
|
||||
obj.seriesId = seriesInfo.seriesId
|
||||
}
|
||||
return obj
|
||||
},
|
||||
findSerialNumberClosest(arr, n) {
|
||||
var absArr = []
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const m = n - arr[i].seriesNumber
|
||||
absArr.push({ index: i, n: Math.abs(m) })
|
||||
}
|
||||
const num = Math.min.apply(null, absArr.map(item => item.n))
|
||||
var mIdx = absArr.findIndex(item => item.n === num)
|
||||
return mIdx
|
||||
},
|
||||
getFirstMarkedSeries(measureDatas, studyList) {
|
||||
var obj = {}
|
||||
var mIdx = measureDatas.findIndex(m => Object.keys(m.MeasureData).length > 0)
|
||||
if (mIdx !== -1) {
|
||||
// 有标记时,显示带标记影像所在序列
|
||||
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[mIdx].StudyId && sd.IsDicom)
|
||||
if (sdIndx > -1) {
|
||||
const seriesList = studyList[sdIndx].SeriesList
|
||||
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
|
||||
// const instanceList = seriesList[srIdx].imageIds
|
||||
const instanceList = seriesList[srIdx].instanceList
|
||||
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId))
|
||||
const series = seriesList[srIdx]
|
||||
series.imageIdIndex = isIdx
|
||||
|
||||
obj.studyIndex = sdIndx
|
||||
obj.seriesIndex = srIdx
|
||||
obj.series = series
|
||||
obj.seriesId = series.seriesId
|
||||
obj.isMarked = true
|
||||
obj.measureData = measureDatas[mIdx]
|
||||
}
|
||||
} else {
|
||||
var seriesObj = null
|
||||
for (let i = 0; i < studyList.length; i++) {
|
||||
const seriesIdx = studyList[i].SeriesList.findIndex(s => s.sliceThickness && parseInt(s.sliceThickness) === 5)
|
||||
if (seriesIdx > -1) {
|
||||
seriesObj = { studyIndex: i, seriesIdx, series: studyList[i].SeriesList[seriesIdx] }
|
||||
break
|
||||
}
|
||||
}
|
||||
if (seriesObj) {
|
||||
obj.studyIndex = seriesObj.studyIndex
|
||||
obj.seriesIndex = seriesObj.seriesIdx
|
||||
seriesObj.series.imageIdIndex = Math.floor(seriesObj.series.imageIds.length / 2)
|
||||
obj.series = seriesObj.series
|
||||
obj.seriesId = seriesObj.series.seriesId
|
||||
obj.isMarked = false
|
||||
} else {
|
||||
const sIdx = studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
// 判断是否存在层厚为5的序列,否则显示第一个检查的第一个序列
|
||||
const series = studyList[sIdx].SeriesList[0]
|
||||
var imageIdIndex = Math.floor(series.imageIds.length / 2)
|
||||
obj.studyIndex = sIdx
|
||||
obj.seriesIndex = 0
|
||||
obj.series = series
|
||||
obj.series.imageIdIndex = imageIdIndex
|
||||
obj.seriesId = series.seriesId
|
||||
obj.isMarked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
},
|
||||
strSimilarity2Number(s, t) {
|
||||
var n = s.length; var m = t.length; var d = []
|
||||
var i, j, s_i, t_j, cost
|
||||
if (n === 0) return m
|
||||
if (m === 0) return n
|
||||
for (i = 0; i <= n; i++) {
|
||||
d[i] = []
|
||||
d[i][0] = i
|
||||
}
|
||||
for (j = 0; j <= m; j++) {
|
||||
d[0][j] = j
|
||||
}
|
||||
for (i = 1; i <= n; i++) {
|
||||
s_i = s.charAt(i - 1)
|
||||
for (j = 1; j <= m; j++) {
|
||||
t_j = t.charAt(j - 1)
|
||||
if (s_i === t_j) {
|
||||
cost = 0
|
||||
} else {
|
||||
cost = 1
|
||||
}
|
||||
d[i][j] = this.Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost)
|
||||
}
|
||||
}
|
||||
return d[n][m]
|
||||
},
|
||||
// 两个字符串的相似程度,并返回相似度百分比
|
||||
strSimilarity2Percent(s, t) {
|
||||
var l = s.length > t.length ? s.length : t.length
|
||||
var d = this.strSimilarity2Number(s, t)
|
||||
return Number((1 - d / l).toFixed(4))
|
||||
},
|
||||
Minimum(a, b, c) {
|
||||
return a < b ? (a < c ? a : c) : (b < c ? b : c)
|
||||
},
|
||||
showSeriesImage(studyIndex, seriesIndex, series) {
|
||||
if (series.isDicom) {
|
||||
this.studyIndex = studyIndex
|
||||
this.seriesIndex = seriesIndex
|
||||
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
|
||||
var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex]
|
||||
this.$emit('loadImageStack', dicomStatck)
|
||||
if (!series.loadStatus) {
|
||||
this.loopLoadStatus = -1
|
||||
series.isLoading = true
|
||||
var p = parseInt(new Date().getTime())
|
||||
series.imageIds.map((imageId, i) => {
|
||||
var priority = ''
|
||||
if (i === 0) {
|
||||
priority = parseInt(new Date().getTime()) * 10
|
||||
} else {
|
||||
priority = --p
|
||||
}
|
||||
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
})
|
||||
if (this.imageList.length > 0) {
|
||||
this.loopLoadStatus = 0
|
||||
this.loopLoad()
|
||||
}
|
||||
}
|
||||
|
||||
DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskId, taskBlindName: this.taskBlindName })
|
||||
} else {
|
||||
// 非Dicom预览
|
||||
this.$emit('previewNoneDicoms', { visitTaskId: this.visitTaskId })
|
||||
}
|
||||
|
||||
store.dispatch('reading/setActiveSeries', series)
|
||||
},
|
||||
setSeriesActive(obj) {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx === -1) return
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
this.studyIndex = obj.studyIndex
|
||||
this.seriesIndex = obj.seriesIndex
|
||||
var activeNames = `${this.studyList[obj.studyIndex].StudyId}`
|
||||
if (this.activeNames.includes(activeNames)) return
|
||||
this.activeNames.push(activeNames)
|
||||
this.loadImages(this.visitTaskList[idx])
|
||||
},
|
||||
selectSeries(obj) {
|
||||
var seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
var i = seriseList.findIndex(i => i.seriesId === obj.seriesId && i.studyId === obj.studyId)
|
||||
if (i === -1) return
|
||||
var idx = i + obj.offset
|
||||
if (idx < 0) {
|
||||
idx = 0
|
||||
} else if (idx >= seriseList.length) {
|
||||
idx = seriseList.length - 1
|
||||
}
|
||||
if (seriseList[idx].seriesIndex === this.seriesIndex && seriseList[idx].studyIndex === this.studyIndex) return
|
||||
this.showSeriesImage(seriseList[idx].studyIndex, seriseList[idx].seriesIndex, seriseList[idx])
|
||||
this.handleActiveSeries(seriseList[idx])
|
||||
},
|
||||
handleActiveSeries(series) {
|
||||
this.studyIndex = series.studyIndex
|
||||
this.seriesIndex = series.seriesIndex
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === series.visitTaskId)
|
||||
if (idx === -1) return
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
var activeNames = `${this.studyList[series.studyIndex].StudyId}`
|
||||
if (this.activeNames.includes(activeNames)) return
|
||||
this.activeNames.push(activeNames)
|
||||
this.loadImages(this.visitTaskList[idx])
|
||||
store.dispatch('reading/setActiveSeries', series)
|
||||
},
|
||||
loadImages(taskInfo) {
|
||||
var priority = taskInfo.IsCurrentTask ? parseInt(new Date().getTime()) : 999
|
||||
|
||||
this.studyList.map((study, studyIndex) => {
|
||||
study.SeriesList.map((series, seriesIndex) => {
|
||||
if (!series.loadStatus) {
|
||||
var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
|
||||
if (series.isBeMark || sliceThickness === 5 || series.instanceCount <= 100) {
|
||||
series.imageIds.map(image => {
|
||||
priority = priority - 1
|
||||
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
this.loopLoad()
|
||||
},
|
||||
loadImages2(taskInfo) {
|
||||
var priority = parseInt(new Date().getTime())
|
||||
// 当前任务只自动下载层厚为5mm 或者影像数量小于 100张
|
||||
if (taskInfo.IsCurrentTask) {
|
||||
this.studyList.map((study, studyIndex) => {
|
||||
study.SeriesList.map((series, seriesIndex) => {
|
||||
var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
|
||||
if (sliceThickness === 5 || series.instanceCount <= 100) {
|
||||
series.imageIds.map(image => {
|
||||
priority = priority - 1
|
||||
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
this.loopLoad()
|
||||
} else {
|
||||
// 非当前任务只自动下载关键序列
|
||||
var idx = this.studyList.findIndex(study => study.IsCriticalSequence)
|
||||
if (idx === -1) return
|
||||
|
||||
this.studyList[idx].SeriesList.forEach((series, seriesIndex) => {
|
||||
if (!series.loadStatus) {
|
||||
series.imageIds.map(image => {
|
||||
priority--
|
||||
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: idx, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
})
|
||||
}
|
||||
})
|
||||
this.loopLoad()
|
||||
}
|
||||
},
|
||||
|
||||
loopLoad() {
|
||||
if (this.imageList.length > 0) {
|
||||
requestPoolManager.startTaskTimer()
|
||||
this.imageList.map(image => {
|
||||
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
|
||||
this.imageLoaded(image, res.data.string('x0020000e'))
|
||||
})
|
||||
})
|
||||
|
||||
this.imageList = []
|
||||
}
|
||||
},
|
||||
// 启动下载序列
|
||||
loadSeries(series, studyIndex, seriesIndex) {
|
||||
console.log('loadSeries')
|
||||
this.loopLoadStatus = -1
|
||||
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', true)
|
||||
const priority = parseInt(new Date().getTime())
|
||||
series.imageIds.map(image => {
|
||||
if (series.imageloadedArr.indexOf(image) === -1) {
|
||||
this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
|
||||
}
|
||||
})
|
||||
if (this.imageList.length > 0) {
|
||||
this.loopLoadStatus = 0
|
||||
this.loopLoad()
|
||||
}
|
||||
},
|
||||
// 暂停下载
|
||||
stopLoadSeries(series, studyIndex, seriesIndex) {
|
||||
console.log('stopLoadSeries')
|
||||
requestPoolManager.removeTask(series.seriesId)
|
||||
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false)
|
||||
},
|
||||
async imageLoaded(image, seriesUid) {
|
||||
await store.dispatch('reading/updateStudyList', { visitTaskId: image.visitTaskId, imageId: image.imageId, seriesUid })
|
||||
},
|
||||
// instance下载成功回调
|
||||
async cornerstoneImageLoaded(e) {
|
||||
await store.dispatch('reading/updateStudyList', { visitTaskId: this.visitTaskId, imageId: e.detail.image.imageId, seriesUid: e.detail.image.data.string('x0020000e') })
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
|
||||
const uri = e.detail.image.sharedCacheKey
|
||||
const index = this.cachedImages.findIndex(item => item.uri === uri)
|
||||
if (index === -1) {
|
||||
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
|
||||
} else {
|
||||
this.cachedImages[index].timestamp = new Date().getTime()
|
||||
}
|
||||
var imageId = e.detail.image.imageId
|
||||
var seriesUid = e.detail.image.data.string('x0020000e')
|
||||
var studyIndex = -1
|
||||
var seriesIndex = -1
|
||||
for (let i = 0; i < this.studyList.length; ++i) {
|
||||
for (let j = 0; j < this.studyList[i].SeriesList.length; ++j) {
|
||||
if (this.studyList[i].SeriesList[j].seriesUid === seriesUid) {
|
||||
studyIndex = i
|
||||
seriesIndex = j
|
||||
break
|
||||
}
|
||||
}
|
||||
if (studyIndex > 0) break
|
||||
}
|
||||
if (seriesIndex < 0) return
|
||||
|
||||
const imageIdIndex = this.studyList[studyIndex].SeriesList[seriesIndex].imageIds.indexOf(imageId)
|
||||
if (imageIdIndex < 0) return
|
||||
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
|
||||
if (this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount >= this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount) {
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.studyList[studyIndex].SeriesList[seriesIndex].loadStatus = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.study-wrapper{
|
||||
>>>.el-progress-bar__inner{
|
||||
transition: width 0s ease;
|
||||
}
|
||||
width:100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.dicom-desc{
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.ps {
|
||||
overflow-anchor: none;
|
||||
touch-action: auto;
|
||||
}
|
||||
.series-active {
|
||||
background-color: #607d8b!important;
|
||||
border: 1px solid #607d8b!important;
|
||||
}
|
||||
>>>.el-progress__text{
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
.series{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
.series-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 95px;
|
||||
// padding: 1px 2px 1px 8px;
|
||||
// margin: 10px 0px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #404040;
|
||||
background-color: #3a3a3a;
|
||||
.el-progress__text{
|
||||
display: none;
|
||||
}
|
||||
.el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
|
||||
.image-preview {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
.image-desc {
|
||||
vertical-align: top;
|
||||
p{
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
color: #ddd;
|
||||
margin: 0px;
|
||||
line-height: 1.5;
|
||||
div{
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.flex-div{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 1px;
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
color: #ddd;
|
||||
padding: 1px;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-collapse{
|
||||
border: none;
|
||||
>>>.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
>>>.el-collapse-item__content{
|
||||
padding-bottom:10px;
|
||||
background-color: #000!important;
|
||||
}
|
||||
>>>.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
padding-left: 5px;
|
||||
height: 40px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,785 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:siteId')">
|
||||
<el-select v-model="searchData.TrialSiteCode" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:subjectId')">
|
||||
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="访视/阅片期名称">
|
||||
<el-input
|
||||
v-model="searchData.TaskName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="角色">
|
||||
<el-select v-model="searchData.ArmEnum" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ArmEnum" :key="'ArmEnum' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="阅片人">
|
||||
<el-select v-model="searchData.DoctorUserId" clearable style="width:120px;">
|
||||
<el-option v-for="item of DoctorUserList" :key="'DoctorUserId' + item.DoctorUserId" :value="item.DoctorUserId" :label="`${item.UserName}(${item.FullName})`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="是否加急">
|
||||
<el-select v-model="searchData.IsUrgent" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="'IsUrgent' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务状态">
|
||||
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskState" :key="'TaskState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务类型">
|
||||
<el-select v-model="searchData.ReadingCategory" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ReadingCategory" :key="'ReadingCategory' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="一致性分析类别">
|
||||
<el-select v-model="searchData.IsSelfAnalysis" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.IsSelfAnalysis" :key="'IsSelfAnalysis' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配状态">
|
||||
<el-select v-model="searchData.TaskAllocationState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskAllocationState" :key="'TaskAllocationState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配时间">
|
||||
<el-date-picker
|
||||
v-model="timeList"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="changeTimeList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openTaskConsistentRule(true)">
|
||||
自身一致性分析
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openTaskConsistentRule(false)">
|
||||
组间一致性分析
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
:label="$t('trials:consistencyCheck:table:isUrgent')"
|
||||
show-overflow-tooltip
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="任务编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
label="中心编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="受试者编号"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="VisitTaskNum"
|
||||
label="访视/阅片期名称"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.TaskName}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
label="任务类型"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsSelfAnalysis"
|
||||
label="一致性分析类别"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsSelfAnalysis" type="primary">{{ $fd('IsSelfAnalysis', scope.row.IsSelfAnalysis) }}</el-tag>
|
||||
<el-tag v-else type="warning">{{ $fd('IsSelfAnalysis', scope.row.IsSelfAnalysis) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ArmEnum"
|
||||
label="角色"
|
||||
min-width="80"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ArmEnum === 1" type="primary">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 2" type="success">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 3" type="info">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 4" type="danger">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 5" type="warning">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 8" style="border-color: #4c2791;color:#4c2791;">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片人"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.UserName}}({{scope.row.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="AllocateTime"
|
||||
label="分配时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SuggesteFinishedTime"
|
||||
label="建议完成时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReadingTaskState"
|
||||
label="阅片状态"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingTaskState === 2" type="primary">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SignTime"
|
||||
label="阅片完成时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReReadingApplyState"
|
||||
label="申请状态"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 1" type="danger">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 2" type="primary">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 3" type="warning">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsReReadingOrBackInfluenceAnalysis"
|
||||
label="是否受到退回影响"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="!scope.row.IsReReadingOrBackInfluenceAnalysis" type="danger">{{ $fd('YesOrNo', scope.row.IsReReadingOrBackInfluenceAnalysis) }}</el-tag>
|
||||
<el-tag v-if="scope.row.IsReReadingOrBackInfluenceAnalysis" type="primary">{{ $fd('YesOrNo', scope.row.IsReReadingOrBackInfluenceAnalysis) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="110"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
:disabled="scope.row.ReadingTaskState !== 2"
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
title="查看阅片结果"
|
||||
@click="lookReadingResults(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="!scope.row.IsReReadingOrBackInfluenceAnalysis || scope.row.TaskState === 1"
|
||||
icon="el-icon-close"
|
||||
circle
|
||||
title="设置为失效"
|
||||
@click="setAnalysisTaskInvalid(scope.row)"
|
||||
/>
|
||||
|
||||
<!-- <el-button-->
|
||||
<!-- :disabled="scope.row.TaskState !== 0 || scope.row.ReadingTaskState !== 2 || scope.row.ReReadingApplyState === 2 || scope.row.ReReadingApplyState === 1"-->
|
||||
<!-- icon="el-icon-collection"-->
|
||||
<!-- circle-->
|
||||
<!-- title="申请重阅"-->
|
||||
<!-- @click="openApplyReReading(scope.row)"-->
|
||||
<!-- />-->
|
||||
<!-- <el-button-->
|
||||
<!-- :disabled="!scope.row.ReReadingApplyState"-->
|
||||
<!-- icon="el-icon-toilet-paper"-->
|
||||
<!-- circle-->
|
||||
<!-- title="退回重阅历史"-->
|
||||
<!-- @click="reReadingHistory(scope.row, 1)"-->
|
||||
<!-- />-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<el-dialog
|
||||
v-if="ReaderRulesVisible"
|
||||
:title="title"
|
||||
:visible.sync="ReaderRulesVisible"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-button size="small" type="primary" style="position: absolute;right: 20px;top: 60px;z-index: 100;" :loading="btnLoading" @click="addReaderRulesForm()">
|
||||
配置{{ title }}规则
|
||||
</el-button>
|
||||
<div class="base-dialog-body" v-if="IsSelfAnalysis" style="margin-top: 32px;">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="TaskConsistentRuleList"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="阅片人"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.AnalysisDoctorUser">
|
||||
{{scope.row.AnalysisDoctorUser.UserName}}({{scope.row.AnalysisDoctorUser.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanVisitCount"
|
||||
label="访视数"
|
||||
min-width="90"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IntervalWeeks"
|
||||
label="间隔周期"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
v-if="IsSelfAnalysis"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsHaveReadingPeriod"
|
||||
label="所选访视是否有阅片期"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsHaveReadingPeriod" size="success">{{$fd('YesOrNo', scope.row.IsHaveReadingPeriod)}}</el-tag>
|
||||
<el-tag v-else size="danger">{{$fd('YesOrNo', scope.row.IsHaveReadingPeriod)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsGenerateGlobalTask"
|
||||
label="是否生成全局阅片任务"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsGenerateGlobalTask" size="success">{{$fd('YesOrNo', scope.row.IsGenerateGlobalTask)}}</el-tag>
|
||||
<el-tag v-else size="danger">{{$fd('YesOrNo', scope.row.IsGenerateGlobalTask)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanSubjectCount"
|
||||
label="计划受试者数"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="GeneratedSubjectCount"
|
||||
label="已生成受试者数"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="110"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-s-check"
|
||||
title="选择"
|
||||
@click="openDoctorConsistentRuleSubjectTable(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ReaderRulesVisible = false">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ReaderRulesVisible2"
|
||||
:title="title"
|
||||
:visible.sync="ReaderRulesVisible2"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-button size="small" type="primary" style="position: absolute;right: 20px;top: 60px;z-index: 100;" :loading="btnLoading" @click="addReaderRulesForm('g')">
|
||||
配置{{ title }}规则
|
||||
</el-button>
|
||||
<GroupConsistentRuleSubjectTable ref="GroupConsistentRuleSubjectTable" style="margin-top: 40px" :IsSelfAnalysis="IsSelfAnalysis" :changeNum="changeNum" @close="() => {ReaderRulesVisible2 = false; ; rowData = {}}" @getList="getList()" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ReaderRulesFormVisible"
|
||||
:title=" `配置${title}规则`"
|
||||
:visible.sync="ReaderRulesFormVisible"
|
||||
width="480px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<ReaderRulesForm :isDisable="isDisable" :data="rowData" :select-list="SelectList" :doctor-user-list="DoctorUserList" :is-self-analysis="IsSelfAnalysis" @close="() => {ReaderRulesFormVisible = false; rowData = {}}" @getList="openTaskConsistentRule(IsSelfAnalysis)" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="DoctorConsistentRuleSubjectTableVisible"
|
||||
title="选择受试者"
|
||||
:visible.sync="DoctorConsistentRuleSubjectTableVisible"
|
||||
width="1000px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<DoctorConsistentRuleSubjectTable :data="rowData" @close="() => {DoctorConsistentRuleSubjectTableVisible = false; ; rowData = {}}" @getList="openTaskConsistentRule(IsSelfAnalysis)" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ApplyforReasonVisible"
|
||||
title="申请重阅"
|
||||
:visible.sync="ApplyforReasonVisible"
|
||||
width="600px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div style="padding:10px;border: 1px solid #e0e0e0;max-height:650px;overflow-y: auto;">
|
||||
<el-form
|
||||
ref="reasonForm"
|
||||
:rules="rules"
|
||||
:model="ApplyforReasonForm"
|
||||
class="demo-ruleForm"
|
||||
size="small"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item
|
||||
label="申请原因"
|
||||
prop="Type"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select')},
|
||||
]"
|
||||
>
|
||||
<el-radio-group v-model="ApplyforReasonForm.Type">
|
||||
<!-- 问题已解决 -->
|
||||
<el-radio :label="1">图像重传</el-radio>
|
||||
<!-- 问题无法解决强制关闭质疑 -->
|
||||
<el-radio :label="2">其他</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 原因 -->
|
||||
<el-form-item v-if="ApplyforReasonForm.Type === 2" label="备注" prop="RequestReReadingReason">
|
||||
<el-input
|
||||
v-model="ApplyforReasonForm.RequestReReadingReason"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:placeholder="$t('common:ruleMessage:specify')"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ApplyforReasonVisible = false;ApplyforReasonForm = { Type: null, RequestReReadingReason: null }">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="applyReReading">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getSelfConsistentDoctorStatList, setAnalysisTaskInvalid, getTrialSiteCodeSelect, getDoctorUserSelectList, getAnalysisTaskList, applyReReading, getDoctorConsistentRuleSubjectList, confirmGenerateConsistentTask, getTaskConsistentRuleList, addOrUpdateTaskConsistentRule, deleteTaskConsistentRule } from '@/api/trials/reading'
|
||||
import ReaderRulesForm from './components/ReaderRulesForm'
|
||||
import DoctorConsistentRuleSubjectTable from './components/DoctorConsistentRuleSubjectTable'
|
||||
import GroupConsistentRuleSubjectTable from './components/GroupConsistentRuleSubjectTable'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getToken } from '@/utils/auth'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
TrialSiteCode: null,
|
||||
IsUrgent: null,
|
||||
TaskName: null,
|
||||
TaskState: null,
|
||||
DoctorUserId: null,
|
||||
ReadingCategory: null,
|
||||
TaskAllocationState: null,
|
||||
BeginAllocateDate: null,
|
||||
EndAllocateDate: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialsNotice',
|
||||
components: { BaseContainer, Pagination, ReaderRulesForm, DoctorConsistentRuleSubjectTable, GroupConsistentRuleSubjectTable },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
maxLength: 0,
|
||||
list: [],
|
||||
siteOptions: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
ReaderRulesVisible: false,
|
||||
DoctorConsistentRuleSubjectTableVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
ReaderRulesVisible2: false,
|
||||
currentData: {},
|
||||
param: {},
|
||||
DoctorUserList: [],
|
||||
btnLoading: false,
|
||||
rowData: {},
|
||||
OtherInfo: null,
|
||||
title: null,
|
||||
SelectList: [],
|
||||
TaskConsistentRuleList: [],
|
||||
isDisable: false,
|
||||
ReaderRulesFormVisible: false,
|
||||
IsSelfAnalysis: true,
|
||||
timeList: [],
|
||||
ApplyforReasonVisible: false,
|
||||
ApplyforReasonForm: {
|
||||
Type: null,
|
||||
RequestReReadingReason: null
|
||||
},
|
||||
rules: {
|
||||
Type: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
RequestReReadingReason: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }]
|
||||
},
|
||||
changeNum: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
this.getSite()
|
||||
this.getDoctorUserSelectList()
|
||||
},
|
||||
methods: {
|
||||
setAnalysisTaskInvalid(row) {
|
||||
this.$confirm('确定要将该一致性任务设置成失效吗?').then(() => {
|
||||
this.loading = true
|
||||
setAnalysisTaskInvalid([
|
||||
row.Id
|
||||
]).then(res => {
|
||||
this.$message.success('设置成功')
|
||||
this.getList()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
this.searchData.BeginAllocateDate = this.timeList[0]
|
||||
this.searchData.EndAllocateDate = this.timeList[1]
|
||||
} else {
|
||||
this.searchData.BeginAllocateDate = null
|
||||
this.searchData.EndAllocateDate = null
|
||||
}
|
||||
},
|
||||
// 重阅历史
|
||||
reReadingHistory(row) {
|
||||
this.$router.push({ path: `/trials/trials-panel/reading/reReadingTracking?trialId=${this.$route.query.trialId}&trialCode=${this.$route.query.trialCode}&researchProgramNo=${this.$route.query.researchProgramNo}&SiteId=${row.SiteId}&SubjectCode=${row.SubjectCode}&TaskName=${row.TaskName}&DoctorUserId=${row.DoctorUserId}` })
|
||||
},
|
||||
// 申请重阅
|
||||
applyReReading() {
|
||||
this.$refs.reasonForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
TaskIdList: [
|
||||
this.rowData.Id
|
||||
],
|
||||
TrialId: this.$route.query.trialId,
|
||||
RequestReReadingType: 2,
|
||||
RequestReReadingReason: this.ApplyforReasonForm.Type === 2 ? this.ApplyforReasonForm.RequestReReadingReason : '图像重传'
|
||||
}
|
||||
applyReReading(params).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('申请重阅成功')
|
||||
this.getList()
|
||||
this.ApplyforReasonVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
lookReadingResults(row) {
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/noneDicomReading?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
openApplyReReading(row) {
|
||||
this.rowData = { ...row }
|
||||
this.ApplyforReasonVisible = true
|
||||
this.ApplyforReasonForm = {
|
||||
Type: null,
|
||||
Remake: null
|
||||
}
|
||||
},
|
||||
editReaderRulesForm(row) {
|
||||
this.rowData = {...row}
|
||||
this.ReaderRulesFormVisible = true
|
||||
},
|
||||
openDoctorConsistentRuleSubjectTable(row) {
|
||||
this.rowData = {...row}
|
||||
this.DoctorConsistentRuleSubjectTableVisible = true
|
||||
},
|
||||
addReaderRulesForm(isg) {
|
||||
this.isDisable = false
|
||||
if (isg) {
|
||||
if (this.$refs['GroupConsistentRuleSubjectTable'].list) {
|
||||
this.$refs['GroupConsistentRuleSubjectTable'].list.forEach(v => {
|
||||
if (v.IsHaveGeneratedTask) {
|
||||
this.isDisable = true
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (this.TaskConsistentRuleList.length > 0) {
|
||||
this.rowData = {...this.TaskConsistentRuleList[0]}
|
||||
this.TaskConsistentRuleList.forEach(v => {
|
||||
if (v.GeneratedSubjectCount) {
|
||||
this.isDisable = true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.rowData = {}
|
||||
}
|
||||
}
|
||||
this.ReaderRulesFormVisible = true
|
||||
},
|
||||
openTaskConsistentRule(IsSelfAnalysis) {
|
||||
this.loading = true
|
||||
if (IsSelfAnalysis) {
|
||||
this.title = '自身一致性分析'
|
||||
getSelfConsistentDoctorStatList({TrialId: this.trialId}).then(res => {
|
||||
this.ReaderRulesFormVisible = false
|
||||
this.DoctorConsistentRuleSubjectTableVisible = false
|
||||
this.TaskConsistentRuleList = res.Result
|
||||
this.IsSelfAnalysis = IsSelfAnalysis
|
||||
this.ReaderRulesVisible = true
|
||||
this.getList()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
this.changeNum ++
|
||||
this.ReaderRulesFormVisible = false
|
||||
this.title = '组间一致性分析'
|
||||
this.IsSelfAnalysis = IsSelfAnalysis
|
||||
this.ReaderRulesVisible2 = true
|
||||
this.loading = false
|
||||
}
|
||||
// getTaskConsistentRuleList({
|
||||
// IsSelfAnalysis: IsSelfAnalysis,
|
||||
// TrialId: this.trialId
|
||||
// }).then(res => {
|
||||
// this.ReaderRulesFormVisible = false
|
||||
// this.DoctorConsistentRuleSubjectTableVisible = false
|
||||
// this.TaskConsistentRuleList = res.Result
|
||||
// this.IsSelfAnalysis = IsSelfAnalysis
|
||||
// this.ReaderRulesVisible = true
|
||||
// })
|
||||
},
|
||||
getDoctorUserSelectList() {
|
||||
getDoctorUserSelectList(this.$route.query.trialId).then(res => {
|
||||
this.DoctorUserList = res.Result
|
||||
if (this.DoctorUserList.length > 0) {
|
||||
this.ReadingType = this.DoctorUserList[0].ReadingType
|
||||
} else {
|
||||
this.$alert('请先去选择项目阅片人')
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getAnalysisTaskList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.OtherInfo = res.OtherInfo
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.ReaderRulesVisible2 = false
|
||||
this.AssignMedicalReviewTaskVisible = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
getSite() {
|
||||
getTrialSiteCodeSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.hidden-row{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-dialog__body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
>>>.el-tag--danger.el-tag--dark {
|
||||
// background-color: #f56c6c!important;
|
||||
border-color: none!important;
|
||||
// color: #fff!important;
|
||||
}
|
||||
>>>#TaskAllocationRuleList thead .el-checkbox__inner{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-descriptions-item__label.has-colon:after{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,350 @@
|
|||
<template>
|
||||
<BaseContainer v-loading="listLoading">
|
||||
<template slot="search-container">
|
||||
|
||||
<span style="margin-left:auto;">
|
||||
<!-- Add -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:visit-plan:add']"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
size="small"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:add') }}
|
||||
</el-button>
|
||||
<!-- 盲态标识 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:visit-plan:add']"
|
||||
type="primary"
|
||||
icon="el-icon-setting"
|
||||
size="small"
|
||||
@click="handleConfig"
|
||||
>
|
||||
{{ $t('trials:visitPlan:button:blindFlag') }}
|
||||
</el-button>
|
||||
<!-- Confirm -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:visit-plan:confirm']"
|
||||
type="primary"
|
||||
icon="el-icon-check"
|
||||
:disabled="!isConfirm"
|
||||
:loading="confirmLoading"
|
||||
size="small"
|
||||
@click="handleConfirm(true)"
|
||||
>
|
||||
{{ $t('trials:visitPlan:button:confirm') }}
|
||||
</el-button>
|
||||
<!-- 调整记录 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:visit-plan:adjust-record']"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="adjustVisible = true"
|
||||
>
|
||||
{{ $t('trials:visitPlan:button:adjustRecord') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
|
||||
:data="list"
|
||||
height="100"
|
||||
stripe
|
||||
>
|
||||
<!-- Visit Name -->
|
||||
<el-table-column
|
||||
prop="VisitName"
|
||||
:label="$t('trials:visitPlan:table:visitName')"
|
||||
show-overflow-tooltip
|
||||
min-width="60"
|
||||
/>
|
||||
<!-- 是否基线 -->
|
||||
<el-table-column
|
||||
prop="IsBaseLine"
|
||||
:label="$t('trials:visitPlan:table:isBaseLine')"
|
||||
show-overflow-tooltip
|
||||
min-width="60"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsBaseLine) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 盲态任务标识 -->
|
||||
<!-- <el-table-column
|
||||
prop="BlindName"
|
||||
:label="$t('trials:visitPlan:table:blindName')"
|
||||
show-overflow-tooltip
|
||||
min-width="80"
|
||||
/> -->
|
||||
<!-- Visit Num -->
|
||||
<el-table-column
|
||||
prop="VisitNum"
|
||||
:label="$t('trials:visitPlan:table:viistNum')"
|
||||
show-overflow-tooltip
|
||||
min-width="60"
|
||||
/>
|
||||
<!-- 访视间隔 -->
|
||||
<el-table-column
|
||||
prop="VisitDay"
|
||||
:label="$t('trials:visitPlan:table:viistDay')"
|
||||
show-overflow-tooltip
|
||||
min-width="60"
|
||||
/>
|
||||
<!-- 窗口 -->
|
||||
<el-table-column
|
||||
v-if="isHaveFirstGiveMedicineDate"
|
||||
prop="VisitWindowLeft"
|
||||
:label="$t('trials:visitPlan:table:window')"
|
||||
show-overflow-tooltip
|
||||
min-width="60"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-show="scope.row.VisitWindowLeft!==0 || scope.row.VisitWindowRight!==0">
|
||||
{{ `${scope.row.VisitWindowLeft}${$t('trials:visitPlan:table:day')} ~ ${scope.row.VisitWindowRight}${$t('trials:visitPlan:table:day')}` }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否确认 -->
|
||||
<el-table-column
|
||||
prop="IsConfirmed"
|
||||
:label="$t('trials:visitPlan:table:isConfirm')"
|
||||
show-overflow-tooltip
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{ $fd('YesOrNo', scope.row.IsConfirmed) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('YesOrNo', scope.row.IsConfirmed) }}</el-tag>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否废除 -->
|
||||
<el-table-column
|
||||
prop="IsDeleted"
|
||||
:label="$t('trials:visitPlan:table:isDeleted')"
|
||||
show-overflow-tooltip
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsDeleted">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- Description -->
|
||||
<el-table-column
|
||||
prop="Description"
|
||||
:label="$t('trials:visitPlan:table:description')"
|
||||
show-overflow-tooltip
|
||||
min-width="80"
|
||||
/>
|
||||
<!-- Time Created -->
|
||||
<el-table-column
|
||||
prop="CreateTime"
|
||||
:label="$t('trials:visitPlan:table:createTime')"
|
||||
show-overflow-tooltip
|
||||
min-width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="hasPermi(['trials:trials-panel:setting:visit-plan:edit'])"
|
||||
:label="$t('common:action:action')"
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- Edit -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:setting:visit-plan:edit']"
|
||||
icon="el-icon-edit-outline"
|
||||
circle
|
||||
:title="$t('common:button:edit')"
|
||||
@click="handleEdit(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<base-model v-if="visit_model.visible" :config="visit_model">
|
||||
<template slot="dialog-body">
|
||||
<VisitPlanForm :row="row" :is-have-first-give-medicine-date="isHaveFirstGiveMedicineDate" @closeDialog="closeDialog" @getList="getList" />
|
||||
</template>
|
||||
</base-model>
|
||||
<!-- 调整记录 -->
|
||||
<el-dialog
|
||||
v-if="adjustVisible"
|
||||
:visible.sync="adjustVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="800px"
|
||||
:title="$t('trials:visitPlan:dialogTitle:record')"
|
||||
>
|
||||
<VisitPlanAdjust />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 配置 -->
|
||||
<el-dialog
|
||||
v-if="config_model.visible"
|
||||
:visible.sync="config_model.visible"
|
||||
:close-on-click-modal="false"
|
||||
width="500px"
|
||||
:title="config_model.title"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-form
|
||||
ref="blindNameForm"
|
||||
v-loading="formLoading"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
size="small"
|
||||
label-width="140px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<!-- 基线盲态标识 -->
|
||||
<el-form-item :label="$t('trials:visitPlan:button:bsBlindFlag')" prop="BlindBaseLineName">
|
||||
<el-input
|
||||
v-model="form.BlindBaseLineName"
|
||||
:disabled="isHaveGeneratedTask"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 随访盲态标识前缀 -->
|
||||
<el-form-item :label="$t('trials:visitPlan:button:visitBlindFlag')" prop="BlindFollowUpPrefix">
|
||||
<el-input
|
||||
v-model="form.BlindFollowUpPrefix"
|
||||
:disabled="isHaveGeneratedTask"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="!isHaveGeneratedTask" class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<el-button v-hasPermi="['trials:trials-panel:setting:visit-plan:add']" type="primary" @click="handleSaveBlindName">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getVisitStageList, confirmTrialVisitPlan, updateVisitBlindName } from '@/api/trials'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import BaseModel from '@/components/BaseModel'
|
||||
import VisitPlanForm from './components/visitPlanForm'
|
||||
import VisitPlanAdjust from './components/visitPlanAdjust'
|
||||
|
||||
export default {
|
||||
name: 'VisitPlan',
|
||||
components: { BaseContainer, BaseModel, VisitPlanForm, VisitPlanAdjust },
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
trialId: '',
|
||||
listLoading: false,
|
||||
row: {},
|
||||
visitPlanConfirmed: true,
|
||||
subjectHasAdded: true,
|
||||
isHaveFirstGiveMedicineDate: false,
|
||||
adjustVisible: false,
|
||||
confirmLoading: false,
|
||||
visit_model: { visible: false, title: '', width: '600px' },
|
||||
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
||||
isConfirm: false,
|
||||
form: { TrialId: '', BlindBaseLineName: '', BlindFollowUpPrefix: '' },
|
||||
rules: {
|
||||
BlindBaseLineName: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
],
|
||||
BlindFollowUpPrefix: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
config_model: { visible: false, title: this.$t('trials:visitPlan:button:blindFlag') }, // '盲态标识'
|
||||
formLoading: false,
|
||||
isHaveGeneratedTask: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
getVisitStageList(this.trialId)
|
||||
.then((res) => {
|
||||
this.listLoading = false
|
||||
this.list = res.Result.VisitPlanList
|
||||
this.visitPlanConfirmed = res.Result.VisitPlanConfirmed
|
||||
this.isHaveFirstGiveMedicineDate = res.Result.IsHaveFirstGiveMedicineDate
|
||||
this.isHaveGeneratedTask = res.Result.IsHaveGeneratedTask
|
||||
this.form.BlindBaseLineName = res.Result.BlindBaseLineName
|
||||
this.form.BlindFollowUpPrefix = res.Result.BlindFollowUpPrefix
|
||||
this.isConfirm = res.Result.VisitPlanList.some(item => { return item.IsConfirmed === false })
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleAdd() {
|
||||
this.row = { TrialId: this.trialId, Id: '', IsBaseLine: false, BlindName: '', VisitWindowLeft: 0, VisitWindowRight: 0, Description: '' }
|
||||
this.timer = new Date().getTime()
|
||||
if (this.list.length === 0) {
|
||||
this.row.VisitName = 'Baseline'
|
||||
this.row.VisitNum = 0
|
||||
this.row.VisitDay = 1
|
||||
} else if (this.list.length === 1) {
|
||||
this.row.VisitName = 'Visit ' + (this.list[0].VisitNum + 1)
|
||||
this.row.VisitNum = this.list[0].VisitNum + 1
|
||||
} else {
|
||||
console.log(1)
|
||||
this.row.VisitName = this.list[this.list.length - 1].VisitName.split(' ')[0] + ' ' + (this.list[this.list.length - 1].VisitNum + 1)
|
||||
this.row.VisitNum = this.list[this.list.length - 1].VisitNum + 1
|
||||
this.row.VisitDay = this.list[this.list.length - 1].VisitDay - this.list[this.list.length - 2].VisitDay + this.list[this.list.length - 1].VisitDay
|
||||
}
|
||||
this.visit_model.title = this.$t('common:button:add')
|
||||
this.visit_model.visible = true
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.row = row
|
||||
this.visit_model.title = this.$t('common:button:edit')
|
||||
this.visit_model.visible = true
|
||||
},
|
||||
handleConfirm() {
|
||||
const msg = this.$t('trials:adjustRecord:message:confirm')
|
||||
this.$confirm(msg, {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}).then(() => {
|
||||
this.confirmLoading = true
|
||||
confirmTrialVisitPlan(this.trialId).then((res) => {
|
||||
this.confirmLoading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
}).catch(() => { this.confirmLoading = false })
|
||||
}).catch(() => {})
|
||||
},
|
||||
closeDialog() {
|
||||
this.visit_model.visible = false
|
||||
},
|
||||
handleSaveBlindName() {
|
||||
this.$refs.blindNameForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.formLoading = true
|
||||
this.form.TrialId = this.trialId
|
||||
updateVisitBlindName(this.form).then((res) => {
|
||||
this.formLoading = false
|
||||
this.config_model.visible = false
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}).catch(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleConfig() {
|
||||
this.config_model.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,496 @@
|
|||
<template>
|
||||
<div class="reading-rule-config-form">
|
||||
<!-- 配置信息表单 -->
|
||||
<el-form
|
||||
ref="readingRulesForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
style="width:800px;"
|
||||
:rules="rules"
|
||||
label-width="260px"
|
||||
size="small"
|
||||
>
|
||||
<!-- 阅片平台 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:imagePlatform')"
|
||||
prop="ImagePlatform"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ImagePlatform"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ImagePlatform"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 阅片工具 -->
|
||||
<el-form-item
|
||||
v-if="form.ImagePlatform === 3"
|
||||
:label="$t('trials:readingUnit:readingRules:title:readingTool')"
|
||||
prop="ReadingTool"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ReadingTool"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingTool"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:readingType')"
|
||||
prop="ReadingType"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ReadingType"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingMethod"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 是否阅片期 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:isReadingPeriod')"
|
||||
prop="IsReadingPeriod"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsReadingPeriod"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsReadingPeriod${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 是否阅片期 -->
|
||||
<el-form-item
|
||||
label="是否自动生成任务"
|
||||
prop="IsAutoCreate"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsAutoCreate"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsAutoCreate${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 是否阅片期 -->
|
||||
<el-form-item
|
||||
label="是否附加评估"
|
||||
prop="IsAdditionalAssessment"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsAdditionalAssessment"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsAdditionalAssessment${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:global')"
|
||||
prop="IsGlobalReading"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsGlobalReading"
|
||||
:disabled="IsMustGlobalReading || isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsGlobalReading${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="form.ReadingType === 2"
|
||||
:label="$t('trials:processCfg:form:ad')"
|
||||
prop="IsArbitrationReading"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsArbitrationReading"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsArbitrationReading${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:clinical')"
|
||||
prop="IsOncologyReading"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsOncologyReading"
|
||||
:disabled="form.IsSystemCriterion || isConfirm || !hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`IsOncologyReading${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 任务展示方式 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:readingTaskViewInOrder')"
|
||||
prop="IsReadingTaskViewInOrder"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsReadingTaskViewInOrder"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
@change="(v) => {
|
||||
if (v) {
|
||||
form.IsReadingShowSubjectInfo = true
|
||||
form.IsReadingShowPreviousResults = true
|
||||
IsNotReadingShowSubjectInfoChange = true
|
||||
form.IseCRFShowInDicomReading = false
|
||||
} else {
|
||||
IsNotReadingShowSubjectInfoChange = false
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.IsReadingTaskViewInOrder"
|
||||
:key="'IsReadingTaskViewInOrder' + item.value"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 任务组织级别 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:readingTaskViewEnum')"
|
||||
prop="ReadingTaskViewEnum"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ReadingTaskViewEnum"
|
||||
:disabled="isConfirm || !isReadingTaskViewInOrder|| (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingTaskViewEnum"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 影像是否有标注 -->
|
||||
<!-- <el-form-item
|
||||
label="影像是否有标注"
|
||||
prop="IsImageLabeled"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsImageLabeled"
|
||||
:disabled="isConfirm"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="'IsImageLabeled'+item.value"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
<!-- IR阅片页面是否显示受试者信息 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:isReadingShowSubjectInfo')"
|
||||
prop="IsReadingShowSubjectInfo"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsReadingShowSubjectInfo"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])) || form.IsReadingTaskViewInOrder"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="'IsReadingShowSubjectInfo'+item.value"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- IR阅片页面是否可以查看既往任务结果 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:isReadingShowPreviousResults')"
|
||||
prop="IsReadingShowPreviousResults"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsReadingShowPreviousResults"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])) || form.IsReadingTaskViewInOrder"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="'IsReadingShowPreviousResults'+item.value"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 修约小数位数 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:digitPlaces')"
|
||||
prop="DigitPlaces"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.DigitPlaces"
|
||||
:disabled="isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit']))"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.DigitPlaces"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- eCRF是否显示在影像阅片页面 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:readingRules:title:isECRFShowInDicomReading')"
|
||||
prop="IseCRFShowInDicomReading"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IseCRFShowInDicomReading"
|
||||
:disabled="form.IsSystemCriterion || isConfirm || (!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])) || form.IsReadingTaskViewInOrder"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="item.label"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="!isConfirm && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])">
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSave(true)"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import { getCriterionReadingInfo, setCriterionReadingInfo } from '@/api/trials'
|
||||
export default {
|
||||
name: 'ReadingRules',
|
||||
props: {
|
||||
trialReadingCriterionId: {
|
||||
type: String,
|
||||
default() {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
TrialId: '',
|
||||
ImagePlatform: null,
|
||||
ReadingTool: 0,
|
||||
ReadingTaskViewEnum: null,
|
||||
IsImageLabeled: null,
|
||||
IsReadingShowSubjectInfo: null,
|
||||
IsReadingShowPreviousResults: null,
|
||||
ReadingType: 1,
|
||||
IsGlobalReading: false,
|
||||
IsArbitrationReading: false,
|
||||
IsOncologyReading: 0,
|
||||
IsReadingTaskViewInOrder: false,
|
||||
IsReadingPeriod: false,
|
||||
// IsReadingTaskViewInOrder: null,
|
||||
ArbitrationRule: null,
|
||||
GlobalUpdateType: null,
|
||||
IsSystemCriterion: true,
|
||||
DigitPlaces: null,
|
||||
IseCRFShowInDicomReading: false,
|
||||
IsAutoCreate: null,
|
||||
IsAdditionalAssessment: null
|
||||
},
|
||||
rules: {
|
||||
ImagePlatform: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
ReadingTool: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
ReadingTaskViewEnum: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsImageLabeled: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsReadingShowSubjectInfo: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsReadingShowPreviousResults: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
ReadingType: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsReadingTaskViewInOrder: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsGlobalReading: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsArbitrationReading: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsOncologyReading: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
DigitPlaces: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IseCRFShowInDicomReading: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
],
|
||||
IsReadingPeriod: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
]
|
||||
// IsReadingTaskViewInOrder: [
|
||||
// { required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||
// ]
|
||||
},
|
||||
loading: false,
|
||||
readingInfo: {},
|
||||
isConfirm: true,
|
||||
isReadingTaskViewInOrder: null,
|
||||
IsMustGlobalReading: false,
|
||||
IsNotReadingShowSubjectInfoChange: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initPage()
|
||||
console.log(this.$d.GlobalAssessType)
|
||||
},
|
||||
methods: {
|
||||
initPage() {
|
||||
this.loading = true
|
||||
const trialId = this.$route.query.trialId
|
||||
getCriterionReadingInfo({ trialId, TrialReadingCriterionId: this.trialReadingCriterionId }).then(res => {
|
||||
this.loading = false
|
||||
for (const k in this.form) {
|
||||
if (res.Result.hasOwnProperty(k)) {
|
||||
this.form[k] = res.Result[k]
|
||||
}
|
||||
}
|
||||
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
|
||||
this.isConfirm = res.Result.IsSign
|
||||
this.IsMustGlobalReading = res.Result.IsMustGlobalReading
|
||||
this.$emit('setConfirm', res.Result.IsSign)
|
||||
this.$emit('setArbitrationReading', res.Result.IsArbitrationReading)
|
||||
this.$emit('setIsClinicalReading', res.Result.IsClinicalReading)
|
||||
this.$emit('setGlobalReading', res.Result.IsGlobalReading)
|
||||
this.$emit('setOncologyReading', res.Result.IsOncologyReading)
|
||||
this.$emit('setDigitPlaces', res.Result.DigitPlaces)
|
||||
if (res.Result.ReadingType === 1) {
|
||||
this.$emit('setArbitrationReading', false)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 配置信息保存
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$refs['readingRulesForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
resolve(false)
|
||||
} else {
|
||||
this.loading = true
|
||||
if (this.form.ReadingType === 1) {
|
||||
this.form.IsArbitrationReading = false
|
||||
}
|
||||
// 保存配置信息
|
||||
this.form.TrialReadingCriterionId = this.trialReadingCriterionId
|
||||
setCriterionReadingInfo(this.form).then(res => {
|
||||
this.loading = false
|
||||
this.$emit('reloadArbitrationRules')
|
||||
this.$emit('setArbitrationReading', this.form.IsArbitrationReading)
|
||||
this.$emit('setIsClinicalReading', this.form.IsClinicalReading)
|
||||
this.$emit('setGlobalReading', this.form.IsGlobalReading)
|
||||
this.$emit('setOncologyReading', this.form.IsOncologyReading)
|
||||
this.$emit('setDigitPlaces', this.form.DigitPlaces)
|
||||
if (this.form.ReadingType === 1) {
|
||||
this.$emit('setArbitrationReading', false)
|
||||
}
|
||||
if (res.IsSuccess && isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
resolve(true)
|
||||
}).catch(_ => {
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.reading-rule-config-form{
|
||||
.fontColor{
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,567 @@
|
|||
<template>
|
||||
<div ref="container" style="width:100%;height:100%" class="dicom-container">
|
||||
<!-- 访视阅片 -->
|
||||
<div v-if="(isReadingTaskViewInOrder || (!isReadingTaskViewInOrder && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
<ReadPage
|
||||
v-if="tabs.includes('read')"
|
||||
:trial-id="trialId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:subject-id="subjectId"
|
||||
:subject-code="subjectCode"
|
||||
:is-show="isShow"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
:is-exists-no-dicom-file="isExistsNoDicomFile"
|
||||
:is-exists-manual="isExistsManual"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report">
|
||||
<ReportPage v-if="tabs.includes('report') && isShow" ref="reportPage" :question-form-change-state="questionFormChangeState" :visit-task-id="visitTaskId" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div v-if="(isReadingTaskViewInOrder || (!isReadingTaskViewInOrder && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
<CustomizeReadPage
|
||||
v-if="tabs.includes('read')"
|
||||
:trial-id="trialId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:subject-id="subjectId"
|
||||
:subject-code="subjectCode"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
:ise-c-r-f-show-in-dicom-reading="IseCRFShowInDicomReading"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
:is-exists-no-dicom-file="isExistsNoDicomFile"
|
||||
:is-exists-manual="isExistsManual"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane v-if="!IseCRFShowInDicomReading" :label="$t('trials:reading:tabTitle:report')" name="report">
|
||||
<CustomizeReportPage v-if="isShow" ref="reportPage" :visit-task-id="visitTaskId" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<!-- 全局阅片 -->
|
||||
<GlobalReview
|
||||
v-else-if="isShow && readingCategory === 2"
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:reading-category="readingCategory"
|
||||
:subject-code="subjectCode"
|
||||
:task-blind-name="taskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
/>
|
||||
<!-- 裁判阅片 -->
|
||||
<AdReview
|
||||
v-else-if="isShow && readingCategory === 4"
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:reading-category="readingCategory"
|
||||
:subject-code="subjectCode"
|
||||
:task-blind-name="taskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
/>
|
||||
|
||||
<!-- 肿瘤学阅片 -->
|
||||
<OncologyReview
|
||||
v-else-if="isShow && readingCategory === 5"
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:reading-category="readingCategory"
|
||||
:subject-code="subjectCode"
|
||||
:task-blind-name="taskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-show-previous-results="isReadingShowPreviousResults"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
/>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
:custom-class="isFullscreen?'full-dialog-container':'dialog-container'"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="isFullscreen"
|
||||
>
|
||||
<span slot="title" class="dialog-footer">
|
||||
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
||||
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
|
||||
<div style="position: absolute;right: 20px;top: 10px;">
|
||||
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isFullscreen=!isFullscreen" />
|
||||
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="dialogVisible = false" />
|
||||
</div>
|
||||
</span>
|
||||
<div style="height: 100%;margin:0;">
|
||||
<ClinicalData
|
||||
v-if="dialogVisible"
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span v-if="!closeCDVisible" slot="footer" class="dialog-footer">
|
||||
<!-- 确认 -->
|
||||
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="tipVisible"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
width="500px"
|
||||
>
|
||||
<span slot="title" class="dialog-footer">
|
||||
<!-- 提示 -->
|
||||
{{ $t('trials:iRecist:warnning:msg44') }}
|
||||
</span>
|
||||
<div>
|
||||
<div>
|
||||
<!-- 您确定当前访视的整体评估结果为PD。根据《独立影像评估章程》,该访视进入iRECIST阅片环节。请对新病灶进行重新评估: -->
|
||||
{{ $t('trials:iRecist:warnning:msg45') }}
|
||||
</div>
|
||||
<div style="color: #f44336;font-size: 12px;margin: 5px;">
|
||||
<!-- (1)新病灶可转为:新靶病灶、新非靶病灶、其它既往新病灶。 -->
|
||||
{{ $t('trials:iRecist:warnning:msg46') }}
|
||||
</div>
|
||||
<div style="color: #f44336;font-size: 12px;margin: 5px;">
|
||||
<!-- (2)新靶病灶:状态为明确的新病灶才能转换为新靶病灶。新靶病灶的选择规则与RECIST1.1相同;如果当前病灶已有标记,但不符合新靶病灶的要求,请清除标记,重新标注。 -->
|
||||
{{ $t('trials:iRecist:warnning:msg47') }}
|
||||
</div>
|
||||
<div style="color: #f44336;font-size: 12px;margin: 5px;">
|
||||
<!-- (3)新非靶病灶:状态为明确的新病灶才能转换为新非靶病灶。新靶病灶的选择规则与RECIST1.1相同。 -->
|
||||
{{ $t('trials:iRecist:warnning:msg48') }}
|
||||
</div>
|
||||
<div style="color: #f44336;font-size: 12px;margin: 5px;">
|
||||
<!-- (4)其它既往新病灶:系统会自动将状态为疑似、消失的新病灶,转换为其它既往新病灶,无需修改。 -->
|
||||
{{ $t('trials:iRecist:warnning:msg49') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<!-- 确认 -->
|
||||
<el-button type="primary" @click="tipVisible = false">{{ $t('trials:reading:button:confirm') }}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials'
|
||||
import ReadPage from './components/ReadPage'
|
||||
import CustomizeReadPage from './customize/CustomizeReadPage'
|
||||
import ReportPage from './components/ReportPage'
|
||||
import CustomizeReportPage from './customize/CustomizeReportPage'
|
||||
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
||||
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
||||
import OncologyReview from '@/views/trials/trials-panel/reading/oncology-review'
|
||||
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
||||
import DicomEvent from './components/DicomEvent'
|
||||
import store from '@/store'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
export default {
|
||||
name: 'Reading',
|
||||
components: {
|
||||
ReadPage,
|
||||
ReportPage,
|
||||
GlobalReview,
|
||||
AdReview,
|
||||
OncologyReview,
|
||||
ClinicalData,
|
||||
CustomizeReadPage,
|
||||
CustomizeReportPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isClinicalDataShow: false,
|
||||
activeName: '',
|
||||
tabs: [],
|
||||
trialId: '',
|
||||
subjectCode: '',
|
||||
subjectId: '',
|
||||
visitTaskId: '',
|
||||
loading: false,
|
||||
readingCategory: null,
|
||||
isReadingShowSubjectInfo: false,
|
||||
isReadingShowPreviousResults: false,
|
||||
isExistsClinicalData: false,
|
||||
isExistsNoDicomFile: false,
|
||||
isNeedReadClinicalData: false,
|
||||
isReadClinicalData: false,
|
||||
digitPlaces: 2,
|
||||
isReadingTaskViewInOrder: false,
|
||||
firstTaskReadingCategory: null,
|
||||
criterionType: null,
|
||||
readingTool: null,
|
||||
dialogVisible: false,
|
||||
TrialReadingCriterionId: null,
|
||||
isNewSubject: null,
|
||||
isShow: false,
|
||||
IseCRFShowInDicomReading: false,
|
||||
isQualityIssueSaved: false,
|
||||
questionFormChangeState: false,
|
||||
questionFormChangeNum: 0,
|
||||
isFullscreen: false,
|
||||
tipVisible: false,
|
||||
closeCDVisible: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
DicomEvent.$on('questionFormChange', (v) => {
|
||||
if (this.questionFormChangeNum !== 0) {
|
||||
this.questionFormChangeState = v
|
||||
}
|
||||
this.questionFormChangeNum++
|
||||
})
|
||||
DicomEvent.$on('getNextTask', () => {
|
||||
store.dispatch('reading/setActiveSeries', {})
|
||||
store.dispatch('reading/setLastCanvasTaskId', '')
|
||||
this.isQualityIssueSaved = false
|
||||
this.firstTaskReadingCategory = this.readingCategory
|
||||
if (!this.isReadingTaskViewInOrder) {
|
||||
// 清除缓存visitTaskList
|
||||
store.dispatch('reading/resetVisitTasks')
|
||||
}
|
||||
this.getTaskInfo(1)
|
||||
})
|
||||
this.activeName = this.$router.currentRoute.query.tabName ? this.$router.currentRoute.query.tabName : 'read'
|
||||
this.tabs.push(this.activeName)
|
||||
this.trialId = this.$router.currentRoute.query.trialId
|
||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.subjectId = this.$router.currentRoute.query.subjectId
|
||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||
this.isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
this.criterionType = this.$router.currentRoute.query.criterionType
|
||||
this.readingTool = this.$router.currentRoute.query.readingTool
|
||||
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
||||
if (this.isNewSubject && this.isReadingTaskViewInOrder) {
|
||||
// 已开始受试者${this.subjectCode}阅片任务
|
||||
var msg = this.$t('trials:reading:warnning:msg1')
|
||||
msg = msg.replace('xxx', this.subjectCode)
|
||||
this.$message.success(msg)
|
||||
changeURLStatic('isNewSubject', '')
|
||||
}
|
||||
if (this.$router.currentRoute.query.TokenKey) {
|
||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||
changeURLStatic('TokenKey', '')
|
||||
}
|
||||
store.dispatch('reading/resetVisitTasks')
|
||||
this.getTaskInfo()
|
||||
window.addEventListener('beforeunload', this.handleWindowClose)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('getNextTask')
|
||||
DicomEvent.$emit('resetOpenWindow')
|
||||
window.removeEventListener('beforeunload', this.handleWindowClose)
|
||||
},
|
||||
methods: {
|
||||
getTaskInfo(flag = 0) {
|
||||
this.loading = true
|
||||
var param = {
|
||||
subjectId: this.subjectId,
|
||||
trialId: this.trialId,
|
||||
subjectCode: this.subjectCode,
|
||||
visitTaskId: this.$router.currentRoute.query.visitTaskId,
|
||||
trialReadingCriterionId: this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
}
|
||||
|
||||
getNextTask(param).then(async res => {
|
||||
this.isShow = false
|
||||
this.visitTaskId = res.Result.VisitTaskId
|
||||
// DicomEvent.$emit('getCustomTableQuestionAnswer', res.Result.VisitTaskId)
|
||||
if (this.subjectId !== res.Result.SubjectId) {
|
||||
store.dispatch('reading/resetVisitTasks')
|
||||
var token = getToken()
|
||||
window.location.href = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${res.Result.SubjectCode}&subjectId=${res.Result.SubjectId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}&isNewSubject=1`
|
||||
} else if (!this.isReadingTaskViewInOrder || res.Result.ReadingCategory !== 1) {
|
||||
store.dispatch('reading/resetVisitTasks')
|
||||
}
|
||||
this.subjectId = res.Result.SubjectId
|
||||
this.subjectCode = res.Result.SubjectCode
|
||||
this.taskBlindName = res.Result.TaskBlindName
|
||||
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
|
||||
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
|
||||
this.isExistsNoDicomFile = res.Result.IsExistsNoDicomFile
|
||||
this.isExistsClinicalData = res.Result.IsExistsClinicalData
|
||||
this.isExistsManual = res.Result.ExistsManual
|
||||
this.isReadClinicalData = res.Result.IsReadClinicalData
|
||||
this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData
|
||||
this.CriterionType = res.Result.CriterionType
|
||||
this.digitPlaces = res.Result.DigitPlaces
|
||||
this.IseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
|
||||
localStorage.setItem('CriterionType', res.Result.CriterionType)
|
||||
localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
|
||||
this.readingCategory = res.Result.ReadingCategory
|
||||
this.questionFormChangeState = false
|
||||
this.questionFormChangeNum = 0
|
||||
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
||||
this.isFullscreen = false
|
||||
this.dialogVisible = true
|
||||
}
|
||||
if (res.Result.ReadingCategory === 1) {
|
||||
this.activeName = 'read'
|
||||
this.tabs = [this.activeName]
|
||||
}
|
||||
if (this.firstTaskReadingCategory === 1 && res.Result.ReadingCategory === 1 && this.isReadingTaskViewInOrder && flag) {
|
||||
this.activeName = 'read'
|
||||
this.tabs = [this.activeName]
|
||||
this.$nextTick(() => {
|
||||
DicomEvent.$emit('getNextVisitInfo')
|
||||
DicomEvent.$emit('getReportInfo')
|
||||
DicomEvent.$emit('resetOpenWindow')
|
||||
})
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.isShow = true
|
||||
this.loading = false
|
||||
if (res.Result.IsFirstChangeTask && res.Result.ReadingTaskState === 0) {
|
||||
this.tipVisible = true
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
store.dispatch('reading/setCurrentReadingTaskState', 2)
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
beforeLeaveCustomize(activeName, oldActiveName) {
|
||||
if (oldActiveName === 'read') {
|
||||
this.isShow = true
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportPage.setScrollTop(1)
|
||||
})
|
||||
} else {
|
||||
this.isShow = false
|
||||
}
|
||||
return Promise.resolve(true)
|
||||
},
|
||||
myConfirm(msg) {
|
||||
return new Promise(resolve => {
|
||||
this.$confirm(msg, {
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
}).then(() => {
|
||||
// this.tabs.push(activeName)
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs.reportPage.setScrollTop(1)
|
||||
// })
|
||||
resolve(true)
|
||||
}).catch(() => {
|
||||
resolve(false)
|
||||
})
|
||||
})
|
||||
},
|
||||
async beforeLeave(activeName, oldActiveName) {
|
||||
if (oldActiveName === 'read') {
|
||||
this.tabs.push(activeName)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportPage.setScrollTop(1)
|
||||
})
|
||||
return Promise.resolve(true)
|
||||
// if (this.questionFormChangeState) {
|
||||
// try {
|
||||
// var msg = this.$t('trials:reading:warnning:msg201')
|
||||
// var isgo = await this.myConfirm(msg)
|
||||
// if (isgo) {
|
||||
// // console.log(this.$refs['questions'])
|
||||
// // this.$refs['questions'].handleSave()
|
||||
// this.tabs.push(activeName)
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs.reportPage.setScrollTop(1)
|
||||
// })
|
||||
// return Promise.resolve(true)
|
||||
// } else {
|
||||
// return Promise.reject(false)
|
||||
// }
|
||||
// } catch (e) {
|
||||
// console.log(e)
|
||||
// }
|
||||
// } else {
|
||||
// this.tabs.push(activeName)
|
||||
// return Promise.resolve(true)
|
||||
// }
|
||||
// var list = null
|
||||
// DicomEvent.$emit('getAllUnSaveLesions', val => {
|
||||
// list = val
|
||||
// })
|
||||
// if (list.length > 0) {
|
||||
// var arr = []
|
||||
// list.map(i => {
|
||||
// arr.push(i.lessionName)
|
||||
// })
|
||||
// // 请先保存${arr.join('、')}病灶信息!
|
||||
// var msg = this.$t('trials:reading:warnning:msg2')
|
||||
// msg = msg.replace('xxx', arr.join('、'))
|
||||
// var isgo = await this.myConfirm(msg)
|
||||
// if (isgo) {
|
||||
// this.tabs.push(activeName)
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs.reportPage.setScrollTop(1)
|
||||
// })
|
||||
// return Promise.resolve(true)
|
||||
// } else {
|
||||
// return Promise.reject(false)
|
||||
// }
|
||||
// } else {
|
||||
// this.tabs.push(activeName)
|
||||
// return Promise.resolve(true)
|
||||
// }
|
||||
// this.tabs.push(activeName)
|
||||
// return Promise.resolve(true)
|
||||
} else {
|
||||
console.log(activeName)
|
||||
if (!this.tabs.includes(activeName)) {
|
||||
this.tabs.push(activeName)
|
||||
}
|
||||
// return true
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
},
|
||||
verifyVisitTaskQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
verifyDefaultQuestionBeAnswer({ visitTaskId: this.visitTaskId }).then(res => {
|
||||
this.loading = false
|
||||
this.isQualityIssueSaved = true
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.isQualityIssueSaved = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleConfirmCD() {
|
||||
this.loading = true
|
||||
var visitTaskId = this.visitTaskId
|
||||
readClinicalData({ visitTaskId }).then(res => {
|
||||
this.loading = false
|
||||
this.dialogVisible = false
|
||||
this.isReadClinicalData = true
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
previewCD() {
|
||||
this.closeCDVisible = true
|
||||
this.isFullscreen = false
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleWindowClose() {
|
||||
DicomEvent.$emit('resetOpenWindow')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.el-message-box__headerbtn{
|
||||
display: none;
|
||||
}
|
||||
.dicom-container{
|
||||
.reading-wrapper{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
background-color: #000;
|
||||
.el-tabs{
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tabs__item{
|
||||
color: #fff;
|
||||
}
|
||||
>>>.el-tabs__header{
|
||||
height: 50px;
|
||||
margin:0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
>>>.el-tabs__content{
|
||||
flex: 1;
|
||||
margin:0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
>>>.el-tabs__item{
|
||||
color: #fff;
|
||||
}
|
||||
>>>.el-tab-pane{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
>>>.hot-keys-label{
|
||||
color: #dfdfdf !important;
|
||||
}
|
||||
>>>.shortcut-key-input span{
|
||||
color: #dfdfdf !important;
|
||||
}
|
||||
// >>>.el-dialog{
|
||||
// background: #1e1e1e;
|
||||
// >>>.el-dialog__body{
|
||||
// padding: 10px;
|
||||
// }
|
||||
|
||||
// }
|
||||
>>>.el-dialog{
|
||||
background: #1e1e1e;
|
||||
border: 1px solid #ddd;
|
||||
color: #ddd;
|
||||
.el-dialog__title{
|
||||
color:#fff;
|
||||
}
|
||||
.el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
.el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
.el-form-item__label{
|
||||
color: #dfdfdf
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
>>>.dialog-container{
|
||||
margin-top: 50px !important;
|
||||
width:75%;
|
||||
height:80%;
|
||||
}
|
||||
>>>.el-dialog__body{
|
||||
padding: 10px;
|
||||
height: calc(100% - 120px);
|
||||
}
|
||||
.el-dialog__header{
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.full-dialog-container{
|
||||
>>>.is-fullscreen .el-dialog__body{
|
||||
height: calc(100% - 120px);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,65 @@
|
|||
/* eslint-disable */
|
||||
export default {
|
||||
'components:uploadvideo:message:xf1': `上传成功`,
|
||||
'components:uploadvideo:message:xf2': `选择的视频不能在浏览器环境播放,请点击转码,等待转码成功之后再进行上传操作`,
|
||||
'components:uploadvideo:message:xf3': `页面未在安全上下文中,不能进行转码,请联系开发人员配置SSL证书`,
|
||||
'components:uploadvideo:message:xf4': `nginx未设置同源隔离,不能进行转码,请联系开发人员配置Nginx请求头`,
|
||||
'components:uploadvideo:message:xf5': `开始转码,请勿关闭窗口或页面`,
|
||||
'components:uploadvideo:message:xf6': `转码成功`,
|
||||
'components:uploadvideo:message:xf7': `文件读取成功,请上传`,
|
||||
'trials:uploadNonDicoms:action:xfuploadvideo': `上传视频文件`,
|
||||
'trials:uploadNonDicoms:title:xfuploadvideo': `上传视频文件`,
|
||||
'trials:uploadNonDicoms:title:xflookvideo': `查看视频文件`,
|
||||
'trials:check:radio:passreason1': `线上质疑解决核查通过`,
|
||||
'trials:check:radio:passreason2': `线下核查通过`,
|
||||
'trials:check:radio:passreason3': `实时阅片跳过核查`,
|
||||
'trials:check:radio:passreason4': `其它`,
|
||||
'trials:check:radio:closereason1': `问题已解决`,
|
||||
'trials:check:radio:closereason2': `问题无法解决强制关闭质疑`,
|
||||
'trials:check:radio:closereason3': `其他`,
|
||||
'trials:qcQuality:label:passReason': `通过原因`,
|
||||
'trials:qcQuality:label:closeReason': `关闭原因`,
|
||||
'trials:consistencyCheck:dialogTitle:xfpassManually': `一致性核查通过`,
|
||||
'trials:consistencyCheck:dialogTitle:xfclose': `关闭一致性核查`,
|
||||
'recompose:form:email': `邮箱`,
|
||||
'recompose:form:role': `角色`,
|
||||
'trials:consistencyCheck:label:passreason': `原因`,
|
||||
'trials:consistencyCheck:label:closereason': `备注`,
|
||||
'trials:trials-panel:taskAllocation': `访视任务分配`,
|
||||
'trials:trials-panel:reading': `阅片`,
|
||||
'trials:trials-panel:refereeAllocation': `裁判任务分配`,
|
||||
'trials:trials-panel:readingTracking': `阅片跟踪`,
|
||||
'trials:trials-panel:reReadingTracking': `重阅跟踪`,
|
||||
'trials:trials-panel:tab:pmMedicalFeedback': `医学审核`,
|
||||
'trials:trials-panel:reading:consistency-analysis': `一致性分析`,
|
||||
'trials:trials-panel:attachments:reReadingTracking': `重阅审批`,
|
||||
'trials:trials-panel:message:notIsHasDicom': `当前文件夹没有DICOM文件,请检查文件夹是否正确!`,
|
||||
'trials:trials-panel:reading:readTaskAllocation': `阅片任务分配`,
|
||||
'trials:trials-panel:attachments:spm-enrollment': `阅片人筛选`,
|
||||
'trials:seletctedReviews:title:language': `语言`,
|
||||
'trials:enrolledReviews:button:sow': `既往阅片情况声明`,
|
||||
'trials:enrolledReviews:button:asow': `入项资格确认书`,
|
||||
'trials:enrolledReviews:button:tackNum': `任务量(未读/已读/总数)`,
|
||||
'DicomViewer:data:customWwc': `自定义调窗`,
|
||||
'CustomWwwcForm:form:label:ww': `窗宽`,
|
||||
'CustomWwwcForm:form:label:wl': `窗位`,
|
||||
'trials:trials-panel:readTaskAllocation:search:ReadPeople': `阅片人`,
|
||||
'trials:trials-panel:readTaskAllocation:button:AllocationRule': `分配规则`,
|
||||
'trials:trials-panel:readTaskAllocation:button:ManualDistribution': `手动分配`,
|
||||
'trials:trials-panel:readTaskAllocation:button:vgoTask': `访视/全局/肿瘤学阅片任务`,
|
||||
'trials:trials-panel:readTaskAllocation:button:adTask': `裁判阅片任务`,
|
||||
'trials:trials-panel:readTaskAllocation:table:TrialSiteCode': `中心编号`,
|
||||
'trials:trials-panel:readTaskAllocation:table:SubjectCode': `受试者编号`,
|
||||
'trials:trials-panel:readTaskAllocation:table:VisitTaskTypeCount': `访视`,
|
||||
'trials:trials-panel:readTaskAllocation:table:GlobalTaskTypeCount': `全局`,
|
||||
'trials:trials-panel:readTaskAllocation:table:JudgeTaskTypeCount': `裁判`,
|
||||
'trials:trials-panel:readTaskAllocation:table:OncologyTaskTypeCount': `肿瘤学阅片`,
|
||||
'trials:trials-panel:readTaskAllocation:table:R1': `阅片人(R1)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:R2': `阅片人(R2)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:AD': `裁判(AD)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:O1': `肿瘤阅片人(O1)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:operation': `操作`,
|
||||
'trials:trials-panel:readTaskAllocation:table:ManualDistribution': `手动分配`,
|
||||
'trials:trials-panel:readTaskAllocation:table:operation': `清除阅片人`,
|
||||
'trials:trials-panel:readTaskAllocation:table:operation': `查看取消历史`,
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
<template>
|
||||
<div ref="monthly_reading_stats" style="width:100%;height:100%;" />
|
||||
</template>
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import { getReadingDataByMonth } from '@/api/dashboard'
|
||||
import { fontSize } from 'utils/fontsize'
|
||||
const Count = 6
|
||||
export default {
|
||||
props: {
|
||||
area: { type: String, default: '' }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
myChart: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
area() {
|
||||
const that = this
|
||||
this.$nextTick(function() {
|
||||
if (that.myChart) {
|
||||
that.myChart.resize()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
initChart(xData, tpArr, adjArr, gArr, totalArr) {
|
||||
const option = {
|
||||
// backgroundColor: '#344b58',
|
||||
title: {
|
||||
text: 'Workload of Past 6 Months',
|
||||
x: '4%',
|
||||
top: 5,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.16)
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
textStyle: {
|
||||
color: '#999'
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
// borderWidth: 0,
|
||||
top: '33%',
|
||||
left: 60,
|
||||
bottom: 25,
|
||||
textStyle: {
|
||||
color: '#999'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
x: '4%',
|
||||
top: '13%',
|
||||
icon: 'circle',
|
||||
itemWidth: fontSize(0.1),
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
},
|
||||
data: ['TP', 'AD', 'GL', 'Total']
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,.1)',
|
||||
// width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 1,
|
||||
show: true,
|
||||
// splitNumber: 15,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
}
|
||||
},
|
||||
data: xData
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,.1 )',
|
||||
// width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,.1)'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: 'TP',
|
||||
type: 'bar',
|
||||
stack: 'Total',
|
||||
barMaxWidth: fontSize(0.4),
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#2fA2FF',
|
||||
|
||||
label: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
},
|
||||
position: 'inside',
|
||||
formatter: function(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: tpArr
|
||||
},
|
||||
|
||||
{
|
||||
name: 'AD',
|
||||
type: 'bar',
|
||||
stack: 'Total',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#27d08a',
|
||||
barBorderRadius: 0,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
},
|
||||
formatter: function(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: adjArr
|
||||
},
|
||||
{
|
||||
name: 'GL',
|
||||
type: 'bar',
|
||||
stack: 'Total',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#2f89cf',
|
||||
barBorderRadius: 0,
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside',
|
||||
formatter: function(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: gArr
|
||||
},
|
||||
{
|
||||
name: 'Total',
|
||||
type: 'line',
|
||||
// "stack": "Total",
|
||||
smooth: true, // 平滑曲线显示
|
||||
symbolSize: 10,
|
||||
symbol: 'circle',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgba(252,230,48,1)',
|
||||
// "barBorderRadius": 0,
|
||||
label: {
|
||||
// position: 'inside',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: fontSize(0.14)
|
||||
},
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: totalArr
|
||||
}
|
||||
],
|
||||
animationEasing: 'elasticOut',
|
||||
animationDelayUpdate: function(idx) {
|
||||
return idx * 5
|
||||
}
|
||||
}
|
||||
if (this.$refs.monthly_reading_stats) {
|
||||
this.myChart = echarts.init(this.$refs.monthly_reading_stats)
|
||||
this.myChart.setOption(option)
|
||||
}
|
||||
},
|
||||
getData() {
|
||||
getReadingDataByMonth(Count).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
if (res.Result) {
|
||||
const xData = []
|
||||
const tpArr = []
|
||||
const adjArr = []
|
||||
const gArr = []
|
||||
const totalArr = []
|
||||
const result = res.Result.reverse()
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
xData.push(result[i].Month)
|
||||
tpArr.push(result[i].Timepoint)
|
||||
adjArr.push(result[i].Adjudication)
|
||||
gArr.push(result[i].Global)
|
||||
const total = result[i].Timepoint + result[i].Adjudication + result[i].Global
|
||||
totalArr.push(total)
|
||||
}
|
||||
this.initChart(xData, tpArr, adjArr, gArr, totalArr)
|
||||
}
|
||||
} else {
|
||||
this.$message({ message: res.ErrorMessage, type: 'error' })
|
||||
}
|
||||
})
|
||||
// .catch(error => {
|
||||
// this.$message({ message: error, type: 'error' })
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,445 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<!-- 搜索框 -->
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true" size="mini">
|
||||
<el-form-item label="器官类型">
|
||||
<el-select v-model="searchData.OrganType" clearable style="width:130px;">
|
||||
<el-option v-for="item of $d.OrganType" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="部位">
|
||||
<el-input v-model="searchData.Part" clearable style="width:130px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="器官">
|
||||
<el-input v-model="searchData.TULOC" clearable style="width:130px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否淋巴结">
|
||||
<el-select v-model="searchData.IsLymphNodes" clearable style="width:130px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" size="mini" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto">
|
||||
<!-- <el-button
|
||||
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="lesionType.visible = true"
|
||||
>
|
||||
病灶类型配置
|
||||
</el-button> -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="lesionType.visible = true"
|
||||
>
|
||||
病灶关联配置
|
||||
</el-button>
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="!isCompleteConfig"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- @click="handleSet"-->
|
||||
<!-- >-->
|
||||
<!-- 默认数据配置-->
|
||||
<!-- </el-button>-->
|
||||
<el-button
|
||||
v-if="!isCompleteConfig"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
</span>
|
||||
|
||||
</template>
|
||||
|
||||
<template slot="main-container">
|
||||
<!-- 受试者列表 -->
|
||||
<el-table
|
||||
ref="organList"
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column type="index" width="90" />
|
||||
<!-- 类型 -->
|
||||
<el-table-column
|
||||
prop="OrganType"
|
||||
label="器官类型"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('OrganType',scope.row.OrganType) }}
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
<!-- 部位 -->
|
||||
<el-table-column
|
||||
prop="Part"
|
||||
label="部位"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="PartEN"
|
||||
label="部位(英文)"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULOC"
|
||||
label="器官"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULOCEN"
|
||||
label="器官(英文)"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULAT"
|
||||
label="位置"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULATEN"
|
||||
label="位置(英文)"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="IsLymphNodes"
|
||||
label="是否淋巴结"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsLymphNodes" type="danger">
|
||||
{{ $fd('ReadingYesOrNo', scope.row.IsLymphNodes) }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('ReadingYesOrNo', scope.row.IsLymphNodes) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsCanEditPosition"
|
||||
label="是否可以编辑"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsCanEditPosition" type="danger">
|
||||
{{ $fd('YesOrNo', scope.row.IsCanEditPosition) }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsCanEditPosition) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Remark"
|
||||
label="备注"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<el-table-column
|
||||
v-if="!isCompleteConfig"
|
||||
:label="$t('common:action:action')"
|
||||
width="200"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
title="编辑"
|
||||
icon="el-icon-edit-outline"
|
||||
@click="handleEdit(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
title="删除"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</template>
|
||||
|
||||
<!-- 新增/编辑 -->
|
||||
<el-dialog
|
||||
v-if="editDialog.visible"
|
||||
:visible.sync="editDialog.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="editDialog.title"
|
||||
width="500px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<OrganForm
|
||||
:data="rowData"
|
||||
:criterion-id="criterionId"
|
||||
@close="editDialog.visible = false"
|
||||
@getList="getList"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 病灶类型 -->
|
||||
<el-dialog
|
||||
v-if="lesionType.visible"
|
||||
:visible.sync="lesionType.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="lesionType.title"
|
||||
width="800px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<LesionTypeTbl
|
||||
:criterion-id="criterionId"
|
||||
:is-complete-config="isCompleteConfig"
|
||||
@close="lesionType.visible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择标准 -->
|
||||
<el-dialog
|
||||
v-if="criterion.visible"
|
||||
:visible.sync="criterion.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="criterion.title"
|
||||
width="500px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
ref="criterionForm"
|
||||
v-loading="formLoading"
|
||||
:model="form"
|
||||
size="small"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<!-- 类型 -->
|
||||
<el-form-item
|
||||
label="标准"
|
||||
prop="CriterionId"
|
||||
:rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
|
||||
]"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.CriterionId"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of criterions"
|
||||
:key="item.CriterionId"
|
||||
:label="item.CriterionName"
|
||||
:value="item.CriterionId"
|
||||
:disabled="criterionId === item.CriterionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button type="primary" @click="criterion.visible = false"> {{ $t('common:button:cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getOrganPageList, deleteOrganInfo, getCriterionNidusList, copySystemCriterionData } from '@/api/dictionary'
|
||||
import { getSystemCriterionList, synchronizeSystemOrganToTrial } from '@/api/trials'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import OrganForm from './OrganForm'
|
||||
import LesionTypeTbl from './LesionTypeTbl'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
SystemCriterionId: '',
|
||||
OrganType: null,
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
TULOC: null,
|
||||
TULAT: null,
|
||||
IsLymphNodes: null,
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'OrgansList',
|
||||
components: { BaseContainer, Pagination, OrganForm, LesionTypeTbl },
|
||||
props: {
|
||||
criterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isCompleteConfig: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
loading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
rowData: {},
|
||||
editDialog: { title: '', visible: false },
|
||||
lesionType: { title: '病灶器官关联关系', visible: false },
|
||||
// lesionTypes: [],
|
||||
criterion: { title: '默认数据配置', visible: false },
|
||||
formLoading: false,
|
||||
form: { CriterionId: '' },
|
||||
criterions: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
list() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.organList.doLayout()
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCriterions()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
synchronizeSystemOrganToTrial() {
|
||||
this.loading = true
|
||||
synchronizeSystemOrganToTrial({
|
||||
TrialReadingCriterionId: this.criterionId,
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.$message.success('同步成功')
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取受试者列表
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.SystemCriterionId = this.criterionId
|
||||
getOrganPageList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
// this.list = res.Result
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getLesionTypes() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getCriterionNidusList({ criterionId: this.criterionId }).then(res => {
|
||||
this.lesionTypes = res.Result
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
// 新增
|
||||
handleAdd() {
|
||||
this.rowData = { SystemCriterionId: this.criterionId }
|
||||
this.editDialog.title = '新增'
|
||||
this.editDialog.visible = true
|
||||
},
|
||||
// 编辑
|
||||
handleEdit(row) {
|
||||
this.rowData = { ...row }
|
||||
this.editDialog.title = '编辑'
|
||||
this.editDialog.visible = true
|
||||
},
|
||||
// 删除
|
||||
handleDelete(row) {
|
||||
this.$confirm('是否确认删除', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = true
|
||||
deleteOrganInfo(row.Id)
|
||||
.then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
this.$message.success('删除成功!')
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
getCriterions() {
|
||||
getSystemCriterionList().then(res => {
|
||||
this.criterions = res.Result
|
||||
})
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleSet() {
|
||||
this.criterion.visible = true
|
||||
this.form.CriterionId = ''
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs['criterionForm'].validate((valid) => {
|
||||
if (!valid) return
|
||||
this.formLoading = true
|
||||
var param = {
|
||||
sourceSystemCriterionId: this.form.CriterionId,
|
||||
newSystemCriterionId: this.criterionId,
|
||||
isCopyQuestion: false
|
||||
}
|
||||
copySystemCriterionData(param).then(res => {
|
||||
this.getList()
|
||||
this.criterion.visible = false
|
||||
this.formLoading = false
|
||||
}).catch(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,222 @@
|
|||
<template>
|
||||
<box-content v-loading="loading">
|
||||
<!-- 搜索框 -->
|
||||
<div class="search">
|
||||
<el-form :inline="true" size="mini" class="base-search-form">
|
||||
<!-- 审核问题 -->
|
||||
<el-form-item :label="$t('trials:qcCfg:table:questionName')">
|
||||
<el-input v-model="searchData.QuestionName" clearable style="width:120px;" />
|
||||
</el-form-item>
|
||||
<!-- 语言类型 -->
|
||||
<el-form-item
|
||||
:label="$t('common:title:languageType')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.LanguageType"
|
||||
style="width:120px;"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.LanguageType"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 类型 -->
|
||||
<el-form-item :label="$t('trials:qcCfg:table:type')">
|
||||
<el-select v-model="searchData.Type" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.QcType" :key="item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 级别: -->
|
||||
<el-form-item :label="$t('trials:qcCfg:table:level')">
|
||||
<el-select v-model="searchData.IsDefeaultViewParent" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.IsDefeaultViewParentLevel" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">{{ $t('common:button:search') }}</el-button>
|
||||
<el-button type="primary" @click="handleReset">{{ $t('common:button:reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto">
|
||||
<el-button type="primary" size="mini" :disabled="selectArr.length<=0" @click="handleSubmit">
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
ref="qsList"
|
||||
:data="list"
|
||||
stripe
|
||||
size="small"
|
||||
height="400"
|
||||
@selection-change="handleSelectChange"
|
||||
@select="handleselect"
|
||||
>
|
||||
<el-table-column type="selection" align="left" width="45" :selectable="handleSelectTable" />
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
:label="$t('trials:qcCfg:table:order')"
|
||||
width="60"
|
||||
/>
|
||||
<!-- 审核问题 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
:label="$t('trials:qcCfg:table:questionName')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 审核问题 -->
|
||||
<el-table-column
|
||||
prop="LanguageType"
|
||||
:label="$t('common:title:languageType')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('LanguageType', scope.row.LanguageType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 类型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:qcCfg:table:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QcType', scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 选项 -->
|
||||
<el-table-column
|
||||
prop="TypeValue"
|
||||
:label="$t('trials:qcCfg:table:typeValue')"
|
||||
show-overflow-tooltip
|
||||
min-width="110"
|
||||
/>
|
||||
|
||||
<!-- 父问题 -->
|
||||
<el-table-column
|
||||
prop="ParentShowOrder"
|
||||
:label="$t('trials:qcCfg:table:parentQs')"
|
||||
show-overflow-tooltip
|
||||
width="120"
|
||||
/>
|
||||
<!-- 父问题触发值 -->
|
||||
<el-table-column
|
||||
prop="ParentTriggerValue"
|
||||
:label="$t('trials:qcCfg:table:parentTriggerValue')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:qcCfg:table:isRequired')"
|
||||
min-width="90"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 启用状态 -->
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
:label="$t('trials:qcCfg:table:isEnable')"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Pagination style="margin-top: 10px" class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</box-content>
|
||||
</template>
|
||||
<script>
|
||||
import { getQCQuestionConfigureList } from '@/api/dictionary'
|
||||
import { batchAddTrialQCQuestionConfigure } from '@/api/trials'
|
||||
import BoxContent from '@/components/BoxContent'
|
||||
import Pagination from '@/components/Pagination'
|
||||
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
Asc: true,
|
||||
SortField: 'ShowOrder',
|
||||
QuestionName: '',
|
||||
LanguageType: null,
|
||||
Type: '',
|
||||
IsEnable: true,
|
||||
IsDefeaultViewParent: false,
|
||||
PageIndex: 1,
|
||||
PageSize: 20
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'QcQuestions',
|
||||
components: { BoxContent, Pagination },
|
||||
data() {
|
||||
return {
|
||||
trialId: '',
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
selectArr: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取受试者列表信息
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
getQCQuestionConfigureList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSelectChange(val) {
|
||||
this.selectArr = val
|
||||
},
|
||||
handleselect(selection, row) {
|
||||
const selected = selection.length && selection.indexOf(row) !== -1
|
||||
console.log(selection)
|
||||
|
||||
var arr = this.list.filter(i => i.ParentId === row.Id)
|
||||
arr.map(item => {
|
||||
this.$refs.qsList.toggleRowSelection(item, selected)
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
this.loading = true
|
||||
batchAddTrialQCQuestionConfigure(this.trialId, this.selectArr).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSelectTable(row) {
|
||||
return !row.ParentId
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.getList()
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,690 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<!-- 中心编号 -->
|
||||
<el-form-item :label="$t('trials:pmMedicalReview:table:siteCode')">
|
||||
<el-select v-model="searchData.TrialSiteCode" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="index"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:pmMedicalReview:table:subjectCode')">
|
||||
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<!-- 任务名称 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:taskName')">
|
||||
<el-input
|
||||
v-model="searchData.TaskName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 阅片人 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:reader')">
|
||||
<el-select v-model="searchData.DoctorUserId" clearable style="width:120px;">
|
||||
<el-option v-for="item of DoctorUserList" :key="'DoctorUserId' + item.DoctorUserId" :value="item.DoctorUserId" :label="`${item.UserName}(${item.FullName})`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 阅片标准 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:criterionName')">
|
||||
<el-select v-model="searchData.TrialReadingCriterionId" clearable style="width:120px;">
|
||||
<el-option v-for="item of trialCriterionList" :key="'TrialReadingCriterionId' + item.TrialReadingCriterionId" :value="item.TrialReadingCriterionId" :label="item.TrialReadingCriterionName" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 是否加急 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:isUrgent')">
|
||||
<el-select v-model="searchData.IsUrgent" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="'IsUrgent' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 阅片任务状态 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:taskState')">
|
||||
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskState" :key="'TaskState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 任务类型 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:taskType')">
|
||||
<el-select v-model="searchData.ReadingCategory" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ReadingCategory" :key="'ReadingCategory' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 阅片状态 -->
|
||||
<!-- <el-form-item style="margin-bottom:10px" label="阅片状态">
|
||||
<el-select v-model="searchData.TaskAllocationState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskAllocationState" :key="'TaskAllocationState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<!-- 审核状态 -->
|
||||
<el-form-item style="margin-bottom:10px" :label="$t('trials:pmMedicalReview:table:auditState')">
|
||||
<el-select v-model="searchData.AuditState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.MedicalReviewAuditState" :key="'AuditState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<!--导出-->
|
||||
<el-button type="primary" icon="el-icon-download" @click="handleExport">
|
||||
{{ $t('common:button:export') }}
|
||||
</el-button>
|
||||
<!-- 筛选 -->
|
||||
<el-button type="primary" v-if="hasPermi(['trials:trials-panel:tab:pmMedicalFeedback:edit'])" @click="openFilter">
|
||||
{{$t('trials:pmMedicalReview:button:select')}}
|
||||
</el-button>
|
||||
<!-- 设置为失效 -->
|
||||
<el-button type="primary" v-if="hasPermi(['trials:trials-panel:tab:pmMedicalFeedback:edit'])" @click="setMedicalReviewInvalid()">
|
||||
{{$t('trials:pmMedicalReview:button:setInvalid')}}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortChange"
|
||||
@selection-change="handleListSelectChange"
|
||||
>
|
||||
<el-table-column type="selection" :selectable="MedicalReviewSelectable" align="left" width="45" />
|
||||
<!-- 是否加急 -->
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
:label="$t('trials:pmMedicalReview:table:isUrgent')"
|
||||
show-overflow-tooltip
|
||||
width="120"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 任务编号 -->
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
:label="$t('trials:pmMedicalReview:table:taskCode')"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 中心编号 -->
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
:label="$t('trials:pmMedicalReview:table:siteCode')"
|
||||
width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 受试者编号 -->
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
:label="$t('trials:pmMedicalReview:table:subjectCode')"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 任务名称 -->
|
||||
<el-table-column
|
||||
prop="VisitTaskNum"
|
||||
:label="$t('trials:pmMedicalReview:table:taskName')"
|
||||
width="130"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.TaskName}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 盲态任务标识 -->
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
:label="$t('trials:pmMedicalReview:table:blindName')"
|
||||
width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
:label="$t('trials:pmMedicalReview:table:taskType')"
|
||||
width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片任务状态 -->
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
:label="$t('trials:pmMedicalReview:table:taskState')"
|
||||
width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 5" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 角色 -->
|
||||
<el-table-column
|
||||
prop="ArmEnum"
|
||||
:label="$t('trials:pmMedicalReview:table:role')"
|
||||
width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ArmEnum === 1" type="primary">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 2" type="success">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 3" type="info">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 4" type="danger">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 5" type="warning">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片人 -->
|
||||
<el-table-column
|
||||
prop="DoctorUser.UserName"
|
||||
:label="$t('trials:pmMedicalReview:table:reader')"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.DoctorUser.UserName">
|
||||
{{scope.row.DoctorUser.UserName}}({{scope.row.DoctorUser.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片标准 -->
|
||||
<el-table-column
|
||||
prop="TrialReadingCriterionName"
|
||||
:label="$t('trials:pmMedicalReview:table:criterionName')"
|
||||
width="180"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 阅片完成时间 -->
|
||||
<el-table-column
|
||||
prop="SignTime"
|
||||
:label="$t('trials:pmMedicalReview:table:signTime')"
|
||||
width="210"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 医学经理 -->
|
||||
<el-table-column
|
||||
prop="MedicalManagerUser.UserName"
|
||||
:label="$t('trials:pmMedicalReview:table:mim')"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.MedicalManagerUser">
|
||||
{{scope.row.MedicalManagerUser.UserName}}({{scope.row.MedicalManagerUser.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 审核分配时间 -->
|
||||
<el-table-column
|
||||
prop="AllocateTime"
|
||||
:label="$t('trials:pmMedicalReview:table:allocateTime')"
|
||||
width="180"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<!-- 任务状态 -->
|
||||
<el-table-column
|
||||
prop="IsInvalid"
|
||||
width="120"
|
||||
:label="$t('trials:pmMedicalReview:table:isInvalid')"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsInvalid" type="danger">
|
||||
{{$fd('IsTakeEffect', scope.row.IsInvalid)}}
|
||||
</el-tag>
|
||||
<el-tag v-else type="primary">
|
||||
{{$fd('IsTakeEffect', scope.row.IsInvalid)}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 审核状态 -->
|
||||
<el-table-column
|
||||
prop="AuditState"
|
||||
:label="$t('trials:pmMedicalReview:table:auditState')"
|
||||
width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="warning" v-if="scope.row.AuditState === 0">{{$fd('MedicalReviewAuditState', scope.row.AuditState)}}</el-tag>
|
||||
<el-tag type="primary" v-if="scope.row.AuditState === 1">{{$fd('MedicalReviewAuditState', scope.row.AuditState)}}</el-tag>
|
||||
<el-tag type="danger" v-if="scope.row.AuditState === 2">{{$fd('MedicalReviewAuditState', scope.row.AuditState)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 审核建议 -->
|
||||
<el-table-column
|
||||
prop="AuditAdviceEnum"
|
||||
:label="$t('trials:pmMedicalReview:table:auditAdvice')"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{$fd('AuditAdvice', scope.row.AuditAdviceEnum)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 阅片人是否认同 -->
|
||||
<el-table-column
|
||||
prop="DoctorUserIdeaEnum"
|
||||
:label="$t('trials:pmMedicalReview:table:whetherAgree')"
|
||||
width="180"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="primary" v-if="scope.row.DoctorUserIdeaEnum === 1"> {{$fd('MedicalReviewDoctorUserIdea', scope.row.DoctorUserIdeaEnum)}} </el-tag>
|
||||
<el-tag type="danger" v-if="scope.row.DoctorUserIdeaEnum === 2"> {{$fd('MedicalReviewDoctorUserIdea', scope.row.DoctorUserIdeaEnum)}} </el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 审核签名时间 -->
|
||||
<el-table-column
|
||||
prop="AuditSignTime"
|
||||
:label="$t('trials:pmMedicalReview:table:auditSignTime')"
|
||||
width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="240"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 查看 -->
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:pmMedicalReview:action:view')"
|
||||
:disabled="scope.row.IsInvalid || scope.row.AuditState !== 2"
|
||||
icon="el-icon-view"
|
||||
@click="handleReadMecialAudit(scope.row)"
|
||||
/>
|
||||
<!-- 设置为失效 -->
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:pmMedicalReview:action:failure')"
|
||||
:disabled="scope.row.IsInvalid || !!scope.row.SignTime"
|
||||
icon="el-icon-close"
|
||||
@click="setMedicalReviewInvalid(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:pmMedicalReview:action:assign')"
|
||||
:disabled="!!scope.row.MedicalManagerUser || scope.row.IsInvalid || !!scope.row.SignTime"
|
||||
icon="el-icon-thumb"
|
||||
@click="assignMedicalReviewTask(scope.row, 1)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:pmMedicalReview:action:cancelAssign')"
|
||||
:disabled="!scope.row.MedicalManagerUser || scope.row.IsInvalid || !!scope.row.SignTime"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="assignMedicalReviewTask(scope.row, 3)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<!-- 筛选 -->
|
||||
<el-dialog
|
||||
v-if="FilterVisible"
|
||||
:title="$t('trials:pmMedicalReview:button:select')"
|
||||
:visible.sync="FilterVisible"
|
||||
width="1200px"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<GenerateMedicalReviewTaskList :trial-criterion-list="trialCriterionList" @getList="getList"></GenerateMedicalReviewTaskList>
|
||||
</el-dialog>
|
||||
<!-- <el-dialog
|
||||
v-if="AddOrEditFilterVisible"
|
||||
:title="title"
|
||||
:visible.sync="AddOrEditFilterVisible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<AddOrEditFilter :data="rowData" :doctor-user-list="DoctorUserList" @close="() => {AddOrEditFilterVisible = false}" @getList="openFilter" />
|
||||
</el-dialog> -->
|
||||
<!-- 分配医学经理 -->
|
||||
<el-dialog
|
||||
v-if="AssignMedicalReviewTaskVisible"
|
||||
:title="$t('trials:pmMedicalReview:allocation:aliocationMIM')"
|
||||
:visible.sync="AssignMedicalReviewTaskVisible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<ReAssignMedicalReviewTask :data="rowData" :select-list="SelectList" :doctor-user-list="MIMOptions" @close="() => {AssignMedicalReviewTaskVisible = false}" @getList="getList" />
|
||||
</el-dialog>
|
||||
<!-- 医学审核详情 -->
|
||||
<el-dialog
|
||||
v-if="auditVisible"
|
||||
:visible.sync="auditVisible"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="true"
|
||||
:title="$t('trials:pmMedicalReview:dialog:medicalReview')"
|
||||
>
|
||||
<MedicalAudit :visit-task-id="currentRow.VisitTaskId" :task-medical-review-id="currentRow.Id" @getList="getList" @close="auditVisible=false" :rowData="currentRow"/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getTrialCriterionList, setMedicalReviewInvalid, assignMedicalReviewTask, getTrialSiteCodeSelect, getMedicalReviewTaskList, getDoctorUserSelectList, getMIMUserList, generateMedicalReviewTask, deleteTaskMedicalReviewRule } from '@/api/trials/reading'
|
||||
import { getMedicalReviewTaskList_Export } from '@/api/export'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import AddOrEditFilter from './components/AddOrEditFilter'
|
||||
import AssignMedicalReviewTask from './components/AssignMedicalReviewTask'
|
||||
import ReAssignMedicalReviewTask from './components/ReAssignMedicalReviewTask'
|
||||
import GenerateMedicalReviewTaskList from './components/GenerateMedicalReviewTaskList'
|
||||
import MedicalAudit from '@/views/trials/trials-panel/reading/mim-medical-audit/components/MedicalAudit'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
TrialSiteCode: null,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
IsUrgent: null,
|
||||
TaskName: null,
|
||||
TaskState: null,
|
||||
DoctorUserId: null,
|
||||
ReadingCategory: null,
|
||||
TaskAllocationState: null,
|
||||
BeginAllocateDate: null,
|
||||
EndAllocateDate: null,
|
||||
AuditState: null,
|
||||
TrialReadingCriterionId: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialsNotice',
|
||||
components: { BaseContainer, Pagination, AddOrEditFilter, AssignMedicalReviewTask, GenerateMedicalReviewTaskList, MedicalAudit, ReAssignMedicalReviewTask },
|
||||
data() {
|
||||
return {
|
||||
auditVisible: null,
|
||||
searchData: searchDataDefault(),
|
||||
maxLength: 0,
|
||||
list: [],
|
||||
siteOptions: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
FilterVisible: false,
|
||||
AssignMedicalReviewTaskVisible: false,
|
||||
AddOrEditFilterVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
currentData: {},
|
||||
param: {},
|
||||
DoctorUserList: [],
|
||||
btnLoading: false,
|
||||
rowData: {},
|
||||
OtherInfo: null,
|
||||
MIMOptions: [],
|
||||
FilterList: [],
|
||||
title: null,
|
||||
SelectList: [],
|
||||
SelectMedicalList: [],
|
||||
distributionInfo: {},
|
||||
currentRow: {},
|
||||
trialCriterionList:[]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
this.getSite()
|
||||
this.getDoctorUserSelectList()
|
||||
this.getMIMUserList()
|
||||
this.getTrialCriterionList()
|
||||
},
|
||||
methods: {
|
||||
handleExport() {
|
||||
getMedicalReviewTaskList_Export(this.searchData).then(res => {
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getTrialCriterionList() {
|
||||
getTrialCriterionList(this.trialId).then(res => {
|
||||
this.trialCriterionList = res.Result
|
||||
}).catch(() => {})
|
||||
},
|
||||
MedicalReviewSelectable(row) {
|
||||
if (row.IsInvalid || row.SignTime) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
handleListSelectChange(e) {
|
||||
this.SelectMedicalList = e
|
||||
},
|
||||
setMedicalReviewInvalid(row) {
|
||||
var params = {}
|
||||
if (row) {
|
||||
params.MedicalReviewIdList = [row.Id]
|
||||
} else {
|
||||
if (this.SelectMedicalList.length === 0) {
|
||||
// '请先勾选医学审核任务'
|
||||
this.$alert(this.$t('trials:pmMedicalReview:message:msg01'))
|
||||
return
|
||||
}
|
||||
params.MedicalReviewIdList = this.SelectMedicalList.map(v => v.Id)
|
||||
}
|
||||
// 确定将该医学审核任务设置为失效吗?
|
||||
this.$confirm(this.$t('trials:pmMedicalReview:message:msg02')).then(() => {
|
||||
this.loading = true
|
||||
params.TrialId = this.trialId
|
||||
setMedicalReviewInvalid(params).then(res => {
|
||||
// '设置成功'
|
||||
this.$message.success(this.$t('trials:pmMedicalReview:message:msg03'))
|
||||
this.getList()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
|
||||
},
|
||||
openAssignMedicalReviewTask() {
|
||||
this.rowData = {}
|
||||
if (this.SelectList.length === 0) {
|
||||
// 请先选择需要分配的医学审核任务
|
||||
this.$alert(this.$t('trials:pmMedicalReview:message:msg04'))
|
||||
return
|
||||
}
|
||||
this.AssignMedicalReviewTaskVisible = true
|
||||
},
|
||||
handleReadMecialAudit(row) {
|
||||
this.currentRow = { ...row }
|
||||
this.auditVisible = true
|
||||
},
|
||||
assignMedicalReviewTask(row, type) {
|
||||
var params = {
|
||||
IdList: [
|
||||
row.Id
|
||||
],
|
||||
taskOptType: type
|
||||
}
|
||||
if (type === 3) {
|
||||
// '确定要取消分配吗?'
|
||||
this.$confirm(this.$t('trials:pmMedicalReview:message:msg05')).then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
assignMedicalReviewTask(params).then(() => {
|
||||
// 取消分配成功
|
||||
this.$message.success(this.$t('trials:pmMedicalReview:message:msg06'))
|
||||
this.getList()
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.rowData = { ...row }
|
||||
this.AssignMedicalReviewTaskVisible = true
|
||||
}
|
||||
},
|
||||
selectable(row) {
|
||||
if (row.MedicalManagerUserId) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
generateMedicalReviewTask() {
|
||||
this.$confirm('确定要应用吗?').then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
generateMedicalReviewTask({
|
||||
trialId: this.trialId
|
||||
}).then(res => {
|
||||
this.$message.success('应用成功')
|
||||
this.loading = false
|
||||
this.getList()
|
||||
this.btnLoading = false
|
||||
this.FilterVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
addOrEdit(row) {
|
||||
if (row) {
|
||||
this.rowData = { ...row }
|
||||
this.title = '编辑'
|
||||
} else {
|
||||
this.rowData = {}
|
||||
this.title = '新增'
|
||||
}
|
||||
this.AddOrEditFilterVisible = true
|
||||
},
|
||||
openFilter() {
|
||||
this.FilterVisible = true
|
||||
this.AddOrEditFilterVisible = false
|
||||
},
|
||||
getDoctorUserSelectList() {
|
||||
getDoctorUserSelectList(this.$route.query.trialId).then(res => {
|
||||
this.DoctorUserList = res.Result
|
||||
if (this.DoctorUserList.length > 0) {
|
||||
this.ReadingType = this.DoctorUserList[0].ReadingType
|
||||
} else {
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getMedicalReviewTaskList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.OtherInfo = res.OtherInfo
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.AssignMedicalReviewTaskVisible = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
getSite() {
|
||||
getTrialSiteCodeSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
getMIMUserList() {
|
||||
getMIMUserList(this.trialId).then(res => {
|
||||
this.MIMOptions = res.Result
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除${row.DoctorUser.UserName}(${row.DoctorUser.FullName})的核查计划吗?`, {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}).then(() => {
|
||||
this.loading = true
|
||||
deleteTaskMedicalReviewRule(row.Id).then(res => {
|
||||
this.loading = false
|
||||
this.$message.success('删除成功')
|
||||
this.openFilter()
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.hidden-row{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-dialog__body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
>>>.el-tag--danger.el-tag--dark {
|
||||
// background-color: #f56c6c!important;
|
||||
border-color: none!important;
|
||||
// color: #fff!important;
|
||||
}
|
||||
>>>#TaskAllocationRuleList thead .el-checkbox__inner{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-descriptions-item__label.has-colon:after{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,403 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<!-- 搜索框 -->
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<!-- 中心编号 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:siteId')">
|
||||
<el-select v-model="searchData.SiteId" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="index"
|
||||
:label="item.TrialSiteCode"
|
||||
:value="item.SiteId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 姓名 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:Name')">
|
||||
<el-input v-model="searchData.UserName" class="mr" clearable style="width:120px;" />
|
||||
</el-form-item>
|
||||
<!-- 角色 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:role')">
|
||||
<el-select
|
||||
v-model="searchData.TrialRoleNameId"
|
||||
style="width:120px;"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of dict.type.SiteSurvey_UserRoles"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 单位 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:organization')">
|
||||
<el-input v-model="searchData.OrganizationName" class="mr" clearable style="width:120px;" />
|
||||
</el-form-item>
|
||||
<!-- 是否生成账号 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:isGenerateAccount')">
|
||||
<el-select
|
||||
v-model="searchData.IsGenerateAccount"
|
||||
style="width:120px;"
|
||||
clearable
|
||||
>
|
||||
<el-option v-for="item of $d.YesOrNo" :key="`IsGenerateAccount${item.value}`" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 用户类型 -->
|
||||
<el-form-item :label="$t('trials:researchStaff:table:userType')">
|
||||
<el-select
|
||||
v-model="searchData.UserTypeId"
|
||||
style="width:120px;"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of userTypeOptions"
|
||||
:key="item.Id"
|
||||
:label="item.UserTypeShortName"
|
||||
:value="item.Id"
|
||||
>
|
||||
<span>{{ item.UserType }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 状态 -->
|
||||
<!-- <el-form-item :label="$t('trials:researchStaff:table:status')">
|
||||
<el-select v-model="searchData.State" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of researchUserState"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<!-- 重置 -->
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<!-- 发邮件 -->
|
||||
<el-form-item>
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:attachments:site-research:summary-record:sendEmail']"
|
||||
type="primary"
|
||||
icon="el-icon-message"
|
||||
:loading="sendEmailLoading"
|
||||
:disabled="selectArr.length === 0"
|
||||
@click="handleSendEmail"
|
||||
>
|
||||
{{ $t('trials:researchRecord:dialogButton:sendEmail') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<!-- 导出 -->
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
:disabled="list.length === 0"
|
||||
@click="handleExport"
|
||||
>
|
||||
{{ $t('common:button:export') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<template slot="main-container">
|
||||
<!-- 系统文件列表 -->
|
||||
<el-table
|
||||
ref="researchUsers"
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:70}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@selection-change="handleSelectChange"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="50"
|
||||
:selectable="handleSelectTable"
|
||||
/>
|
||||
<el-table-column type="index" width="50" />
|
||||
<!-- 中心编号 -->
|
||||
<el-table-column
|
||||
prop="TrialSiteSurvey.TrialSiteCode"
|
||||
:label="$t('trials:researchStaff:table:siteId')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">{{ `${scope.row.TrialSiteSurvey.TrialSiteCode}` }}</template>
|
||||
</el-table-column>
|
||||
<!-- 中心名称 -->
|
||||
<el-table-column
|
||||
prop="TrialSiteSurvey.SiteName"
|
||||
:label="$t('trials:researchStaff:table:siteName')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">{{ `${scope.row.TrialSiteSurvey.SiteName}` }}</template>
|
||||
</el-table-column>
|
||||
<!-- 姓名 -->
|
||||
<el-table-column
|
||||
prop="LastName"
|
||||
:label="$t('trials:researchStaff:table:Name')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">{{ `${scope.row.LastName} / ${scope.row.FirstName}` }}</template>
|
||||
</el-table-column>
|
||||
<!-- 角色 -->
|
||||
<el-table-column
|
||||
prop="TrialRoleName"
|
||||
:label="$t('trials:researchStaff:table:role')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- 电话号码 -->
|
||||
<el-table-column
|
||||
prop="Phone"
|
||||
:label="$t('trials:researchStaff:table:phone')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="120"
|
||||
/>
|
||||
<!-- 邮箱 -->
|
||||
<el-table-column
|
||||
prop="Email"
|
||||
:label="$t('trials:researchStaff:table:email')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="150"
|
||||
/>
|
||||
<!-- 单位 -->
|
||||
<el-table-column
|
||||
prop="OrganizationName"
|
||||
:label="$t('trials:researchStaff:table:organization')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- 是否生成账号 -->
|
||||
<el-table-column
|
||||
prop="IsGenerateAccount"
|
||||
:label="$t('trials:researchStaff:table:isGenerateAccount')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="130"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsGenerateAccount) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="State"-->
|
||||
<!-- :label="$t('trials:researchStaff:table:status')"-->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- sortable="custom"-->
|
||||
<!-- min-width="130"-->
|
||||
<!-- >-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- {{ $fd('researchUserState', scope.row.State) }}-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
|
||||
<!-- 用户类型 -->
|
||||
<el-table-column
|
||||
prop="UserType"
|
||||
:label="$t('trials:researchStaff:table:userType')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- 是否加入 -->
|
||||
<el-table-column
|
||||
prop="IsJoin"
|
||||
:label="$t('trials:researchStaff:table:isJoin')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsJoin" type="info">{{ $fd('IsJoin', scope.row.IsJoin) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('IsJoin', scope.row.IsJoin) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { trialSiteSurveyUserList, getTrialSiteSelect, getUserTypeList, trialSiteUserSummaryListExport, sendSiteSurveyUserJoinEmail } from '@/api/trials'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
SortField: '',
|
||||
Asc: true,
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
SiteId: '',
|
||||
UserTypeId: '',
|
||||
IsGenerateAccount: null,
|
||||
TrialRoleNameId: '',
|
||||
UserName: '',
|
||||
OrganizationName: '',
|
||||
FormWriterKeyInfo: '',
|
||||
State: ''
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'SiteResearchList',
|
||||
components: { BaseContainer, Pagination },
|
||||
dicts: ['SiteSurvey_UserRoles'],
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
loading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
trialId: this.$route.query.trialId,
|
||||
siteOptions: [],
|
||||
userTypeOptions: [],
|
||||
selectArr: [],
|
||||
sendEmailLoading: false
|
||||
// researchUserState: [
|
||||
// { label: '未邀请', value: 0 },
|
||||
// { label: '已邀请', value: 1 },
|
||||
// { label: '已确认', value: 2 },
|
||||
// { label: '已拒绝', value: 3 },
|
||||
// { label: '超时', value: 4 }
|
||||
// ]
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
this.getSite()
|
||||
this.getUserType()
|
||||
},
|
||||
methods: {
|
||||
// 获取系统文件数据
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
trialSiteSurveyUserList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取调查表用户已勾选人员信息
|
||||
handleSelectChange(val) {
|
||||
this.selectArr = val
|
||||
},
|
||||
// handleSelectable(row) {
|
||||
// // 已超时||已拒绝
|
||||
// // if (row.State === 3 || row.State === 4) {
|
||||
// // return true
|
||||
// // } else {
|
||||
// // return false
|
||||
// // }
|
||||
// return true
|
||||
// },
|
||||
// 发送邮件
|
||||
handleSendEmail() {
|
||||
this.sendEmailLoading = true
|
||||
const param = {
|
||||
TrialId: this.trialId,
|
||||
TrialSiteSurveyId: this.selectArr[0].TrialSiteSurveyId,
|
||||
BaseUrl: `${location.protocol}//${location.host}/login`,
|
||||
RouteUrl: `${location.protocol}//${location.host}/email-recompose`,
|
||||
UserList: this.selectArr
|
||||
}
|
||||
sendSiteSurveyUserJoinEmail(param).then(() => {
|
||||
this.sendEmailLoading = false
|
||||
// 发送成功
|
||||
this.$message.success(this.$t('trials:researchStaff:message:sendEmalil'))
|
||||
this.getList()
|
||||
}).catch(() => { this.sendEmailLoading = false })
|
||||
// var joinUrl = `${location.protocol}//${location.host}/#/joinVerify`
|
||||
// var sendEmailUserArr = this.selectArr.map((v) => { return { Id: v.Id, Email: v.Email, IsSystemUser: v.IsSystemUser, SystemUserId: v.SystemUserId } })
|
||||
// sendInviteEmail({
|
||||
// TrialId: this.trialId,
|
||||
// SendUsers: sendEmailUserArr,
|
||||
// BaseUrl: BaseUrl,
|
||||
// RouteUrl: joinUrl
|
||||
// }).then(() => {
|
||||
// this.sendEmailLoading = false
|
||||
// this.$message.success('Saved successfully!')
|
||||
// this.getResearchUserList()
|
||||
// }).catch(() => { this.sendEmailLoading = false })
|
||||
},
|
||||
// 导出
|
||||
handleExport() {
|
||||
this.searchData.TrialId = this.trialId
|
||||
this.loading = true
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { SortField, Asc, PageIndex, PageSize, ...param } = { ...this.searchData }
|
||||
trialSiteUserSummaryListExport({ ...param }).then(data => {
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
// 获取site下拉框数据
|
||||
getSite() {
|
||||
getTrialSiteSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
// 获取系统用户类型
|
||||
getUserType() {
|
||||
getUserTypeList(3).then(res => {
|
||||
this.userTypeOptions = res.Result
|
||||
})
|
||||
},
|
||||
handleSelectTable(row) {
|
||||
return row.IsGenerateSuccess && !row.IsJoin
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
this.$nextTick(() => {
|
||||
this.$refs.researchUsers.clearSort()
|
||||
})
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.getList()
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,689 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:siteId')">
|
||||
<el-select v-model="searchData.SiteId" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="index"
|
||||
:label="item.TrialSiteCode"
|
||||
:value="item.SiteId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:subjectId')">
|
||||
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="访视/阅片期名称">
|
||||
<el-input
|
||||
v-model="searchData.TaskName"
|
||||
style="width:100px;"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="阅片人">
|
||||
<el-select v-model="searchData.DoctorUserId" clearable style="width:120px;">
|
||||
<el-option v-for="item of DoctorUserList" :key="'DoctorUserId' + item.DoctorUserId" :value="item.DoctorUserId" :label="item.UserName" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="是否加急">
|
||||
<el-select v-model="searchData.IsUrgent" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="'IsUrgent' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="任务类型">
|
||||
<el-select v-model="searchData.ReadingCategory" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.ReadingCategory" :key="'ReadingCategory' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配状态">
|
||||
<el-select v-model="searchData.TaskAllocationState" clearable style="width:120px;">
|
||||
<el-option v-for="item of $d.TaskAllocationState" :key="'TaskAllocationState' + item.label" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px" label="分配时间">
|
||||
<el-date-picker
|
||||
v-model="timeList"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@change="changeTimeList"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom:10px">
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openTaskConsistentRule(true)">
|
||||
自身一致性分析
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openTaskConsistentRule(false)">
|
||||
组间一致性分析
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column
|
||||
prop="IsUrgent"
|
||||
:label="$t('trials:consistencyCheck:table:isUrgent')"
|
||||
show-overflow-tooltip
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsUrgent" type="danger">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="任务编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
label="中心编号"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="受试者编号"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskName"
|
||||
label="访视/阅片期名称"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="访视盲态名称"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReadingCategory"
|
||||
label="阅片类别"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 2" type="info">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 4" type="danger">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReadingCategory === 5" type="warning">{{ $fd('ReadingCategory', scope.row.ReadingCategory) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
label="一致性分析类别"
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsSelfAnalysis" type="primary">{{ $fd('IsSelfAnalysis', scope.row.IsSelfAnalysis) }}</el-tag>
|
||||
<el-tag v-else type="warning">{{ $fd('IsSelfAnalysis', scope.row.IsSelfAnalysis) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="role"
|
||||
label="角色"
|
||||
min-width="80"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ArmEnum === 1" type="primary">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 2" type="success">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 3" type="info">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 4" type="danger">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
<el-tag v-if="scope.row.ArmEnum === 5" type="warning">{{$fd('ArmEnum', scope.row.ArmEnum)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="DoctorUser.UserName"
|
||||
label="阅片人"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.UserName}}({{scope.row.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="TaskState"
|
||||
label="任务状态"
|
||||
min-width="100"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 1" type="info">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="AllocateTime"
|
||||
label="分配时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SuggesteFinishedTime"
|
||||
label="建议完成时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReadingTaskState"
|
||||
label="阅片状态"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingTaskState === 2" type="primary">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SignTime"
|
||||
label="阅片完成时间"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ReReadingApplyState"
|
||||
label="申请状态"
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 1" type="danger">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 2" type="primary">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
<el-tag v-if="scope.row.ReReadingApplyState === 3" type="warning">{{ $fd('ReReadingApplyState', scope.row.ReReadingApplyState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="210"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
:disabled="scope.row.ReadingTaskState !== 2"
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
title="查看阅片结果"
|
||||
@click="lookReadingResults(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="scope.row.TaskState !== 0 || scope.row.ReadingTaskState !== 2 || scope.row.ReReadingApplyState === 2 || scope.row.ReReadingApplyState === 1"
|
||||
icon="el-icon-collection"
|
||||
circle
|
||||
title="申请重阅"
|
||||
@click="openApplyReReading(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
:disabled="!scope.row.ReReadingApplyState"
|
||||
icon="el-icon-toilet-paper"
|
||||
circle
|
||||
title="退回重阅历史"
|
||||
@click="reReadingHistory(scope.row, 1)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<el-dialog
|
||||
v-if="ReaderRulesVisible"
|
||||
:title="title"
|
||||
:visible.sync="ReaderRulesVisible"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-button size="small" type="primary" style="position: absolute;right: 20px;top: 60px;z-index: 100;" :loading="btnLoading" @click="addReaderRulesForm">
|
||||
配置{{ title }}规则
|
||||
</el-button>
|
||||
<div class="base-dialog-body" style="margin-top: 32px;">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="TaskConsistentRuleList"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="TaskCode"
|
||||
label="阅片人"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope" v-if="scope.row.AnalysisDoctorUser">
|
||||
{{scope.row.AnalysisDoctorUser.UserName}}({{scope.row.AnalysisDoctorUser.FullName}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanVisitCount"
|
||||
label="访视数"
|
||||
min-width="90"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IntervalWeeks"
|
||||
label="间隔周期"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
v-if="IsSelfAnalysis"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsHaveReadingPeriod"
|
||||
label="所选访视是否有阅片期"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsHaveReadingPeriod" size="success">{{$fd('YesOrNo', scope.row.IsHaveReadingPeriod)}}</el-tag>
|
||||
<el-tag v-else size="danger">{{$fd('YesOrNo', scope.row.IsHaveReadingPeriod)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsGenerateGlobalTask"
|
||||
label="是否生成全局阅片任务"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsGenerateGlobalTask" size="success">{{$fd('YesOrNo', scope.row.IsGenerateGlobalTask)}}</el-tag>
|
||||
<el-tag v-else size="danger">{{$fd('YesOrNo', scope.row.IsGenerateGlobalTask)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanSubjectCount"
|
||||
label="计划受试者数"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="GeneratedSubjectCount"
|
||||
label="已生成受试者数"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="110"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-s-check"
|
||||
title="选择"
|
||||
@click="openDoctorConsistentRuleSubjectTable(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ReaderRulesVisible = false">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ReaderRulesFormVisible"
|
||||
:title=" `配置${title}规则`"
|
||||
:visible.sync="ReaderRulesFormVisible"
|
||||
width="480px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<ReaderRulesForm :data="rowData" :select-list="SelectList" :doctor-user-list="DoctorUserList" :is-self-analysis="IsSelfAnalysis" @close="() => {ReaderRulesFormVisible = false; rowData = {}}" @getList="openTaskConsistentRule(IsSelfAnalysis)" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="DoctorConsistentRuleSubjectTableVisible"
|
||||
title="选择受试者"
|
||||
:visible.sync="DoctorConsistentRuleSubjectTableVisible"
|
||||
width="1000px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<DoctorConsistentRuleSubjectTable :data="rowData" @close="() => {DoctorConsistentRuleSubjectTableVisible = false; ; rowData = {}}" @getList="openTaskConsistentRule(IsSelfAnalysis)" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ApplyforReasonVisible"
|
||||
title="申请重阅"
|
||||
:visible.sync="ApplyforReasonVisible"
|
||||
width="600px"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div style="padding:10px;border: 1px solid #e0e0e0;max-height:650px;overflow-y: auto;">
|
||||
<el-form
|
||||
ref="reasonForm"
|
||||
:rules="rules"
|
||||
:model="ApplyforReasonForm"
|
||||
class="demo-ruleForm"
|
||||
size="small"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item
|
||||
label="申请原因"
|
||||
prop="Type"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select')},
|
||||
]"
|
||||
>
|
||||
<el-radio-group v-model="ApplyforReasonForm.Type">
|
||||
<!-- 问题已解决 -->
|
||||
<el-radio :label="1">图像重传</el-radio>
|
||||
<!-- 问题无法解决强制关闭质疑 -->
|
||||
<el-radio :label="2">其他</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 原因 -->
|
||||
<el-form-item v-if="ApplyforReasonForm.Type === 2" label="备注" prop="RequestReReadingReason">
|
||||
<el-input
|
||||
v-model="ApplyforReasonForm.RequestReReadingReason"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:placeholder="$t('common:ruleMessage:specify')"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ApplyforReasonVisible = false;ApplyforReasonForm = { Type: null, RequestReReadingReason: null }">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="applyReReading">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getTrialSiteSelect } from '@/api/trials'
|
||||
import { getSelfConsistentDoctorStatList, getDoctorUserSelectList, getAnalysisTaskList, applyReReading, getDoctorConsistentRuleSubjectList, confirmGenerateConsistentTask, getTaskConsistentRuleList, addOrUpdateTaskConsistentRule, deleteTaskConsistentRule } from '@/api/trials/reading'
|
||||
import ReaderRulesForm from './components/ReaderRulesForm'
|
||||
import DoctorConsistentRuleSubjectTable from './components/DoctorConsistentRuleSubjectTable'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
IsUrgent: null,
|
||||
TaskName: null,
|
||||
DoctorUserId: null,
|
||||
ReadingCategory: null,
|
||||
TaskAllocationState: null,
|
||||
BeginAllocateDate: null,
|
||||
EndAllocateDate: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialsNotice',
|
||||
components: { BaseContainer, Pagination, ReaderRulesForm, DoctorConsistentRuleSubjectTable },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
maxLength: 0,
|
||||
list: [],
|
||||
siteOptions: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
ReaderRulesVisible: false,
|
||||
DoctorConsistentRuleSubjectTableVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
currentData: {},
|
||||
param: {},
|
||||
DoctorUserList: [],
|
||||
btnLoading: false,
|
||||
rowData: {},
|
||||
OtherInfo: null,
|
||||
title: null,
|
||||
SelectList: [],
|
||||
TaskConsistentRuleList: [],
|
||||
ReaderRulesFormVisible: false,
|
||||
IsSelfAnalysis: true,
|
||||
timeList: [],
|
||||
ApplyforReasonVisible: false,
|
||||
ApplyforReasonForm: {
|
||||
Type: null,
|
||||
RequestReReadingReason: null
|
||||
},
|
||||
rules: {
|
||||
Type: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
RequestReReadingReason: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }]
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
this.getSite()
|
||||
this.getDoctorUserSelectList()
|
||||
},
|
||||
methods: {
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
this.searchData.BeginAllocateDate = this.timeList[0]
|
||||
this.searchData.EndAllocateDate = this.timeList[1]
|
||||
} else {
|
||||
this.searchData.BeginAllocateDate = null
|
||||
this.searchData.EndAllocateDate = null
|
||||
}
|
||||
},
|
||||
// 重阅历史
|
||||
reReadingHistory(row) {
|
||||
this.$router.push({ path: `/trials/trials-panel/reading/reReadingTracking?trialId=${this.$route.query.trialId}&trialCode=${this.$route.query.trialCode}&researchProgramNo=${this.$route.query.researchProgramNo}&SiteId=${row.SiteId}&SubjectCode=${row.SubjectCode}&TaskName=${row.TaskName}&DoctorUserId=${row.DoctorUserId}` })
|
||||
},
|
||||
// 申请重阅
|
||||
applyReReading() {
|
||||
this.$refs.reasonForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
TaskIdList: [
|
||||
this.rowData.Id
|
||||
],
|
||||
TrialId: this.$route.query.trialId,
|
||||
RequestReReadingType: 2,
|
||||
RequestReReadingReason: this.ApplyforReasonForm.Type === 2 ? this.ApplyforReasonForm.RequestReReadingReason : '图像重传'
|
||||
}
|
||||
applyReReading(params).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('申请重阅成功')
|
||||
this.getList()
|
||||
this.ApplyforReasonVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
lookReadingResults(row) {
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/noneDicomReading?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
openApplyReReading(row) {
|
||||
this.rowData = { ...row }
|
||||
this.ApplyforReasonVisible = true
|
||||
this.ApplyforReasonForm = {
|
||||
Type: null,
|
||||
Remake: null
|
||||
}
|
||||
},
|
||||
editReaderRulesForm(row) {
|
||||
this.rowData = {...row}
|
||||
this.ReaderRulesFormVisible = true
|
||||
},
|
||||
openDoctorConsistentRuleSubjectTable(row) {
|
||||
this.rowData = {...row}
|
||||
this.DoctorConsistentRuleSubjectTableVisible = true
|
||||
},
|
||||
addReaderRulesForm() {
|
||||
if (this.TaskConsistentRuleList.length > 0) {
|
||||
this.rowData = {...this.TaskConsistentRuleList[0]}
|
||||
} else {
|
||||
this.rowData = {}
|
||||
}
|
||||
this.ReaderRulesFormVisible = true
|
||||
},
|
||||
openTaskConsistentRule(IsSelfAnalysis) {
|
||||
this.loading = true
|
||||
if (IsSelfAnalysis) {
|
||||
this.title = '自身一致性分析'
|
||||
getSelfConsistentDoctorStatList({TrialId: this.trialId}).then(res => {
|
||||
this.ReaderRulesFormVisible = false
|
||||
this.DoctorConsistentRuleSubjectTableVisible = false
|
||||
this.TaskConsistentRuleList = res.Result
|
||||
this.IsSelfAnalysis = IsSelfAnalysis
|
||||
this.ReaderRulesVisible = true
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
this.title = '组间一致性分析'
|
||||
this.loading = false
|
||||
}
|
||||
// getTaskConsistentRuleList({
|
||||
// IsSelfAnalysis: IsSelfAnalysis,
|
||||
// TrialId: this.trialId
|
||||
// }).then(res => {
|
||||
// this.ReaderRulesFormVisible = false
|
||||
// this.DoctorConsistentRuleSubjectTableVisible = false
|
||||
// this.TaskConsistentRuleList = res.Result
|
||||
// this.IsSelfAnalysis = IsSelfAnalysis
|
||||
// this.ReaderRulesVisible = true
|
||||
// })
|
||||
},
|
||||
getDoctorUserSelectList() {
|
||||
getDoctorUserSelectList(this.$route.query.trialId).then(res => {
|
||||
this.DoctorUserList = res.Result
|
||||
if (this.DoctorUserList.length > 0) {
|
||||
this.ReadingType = this.DoctorUserList[0].ReadingType
|
||||
} else {
|
||||
this.$alert('请先去选择项目阅片人')
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getAnalysisTaskList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.OtherInfo = res.OtherInfo
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.AssignMedicalReviewTaskVisible = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
getSite() {
|
||||
getTrialSiteSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.hidden-row{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-dialog__body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
>>>.el-tag--danger.el-tag--dark {
|
||||
// background-color: #f56c6c!important;
|
||||
border-color: none!important;
|
||||
// color: #fff!important;
|
||||
}
|
||||
>>>#TaskAllocationRuleList thead .el-checkbox__inner{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-descriptions-item__label.has-colon:after{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,103 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<el-form
|
||||
ref="MedicalManagerDataForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
label-width="140px"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="阅片人" prop="MedicalManagerUserId">
|
||||
<el-select v-model="form.MedicalManagerUserId" clearable>
|
||||
<el-option v-for="item of doctorUserList" :label="`${item.UserName}(${item.FullName})`" :value="item.UserId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { assignMedicalReviewTask } from '@/api/trials/reading'
|
||||
|
||||
export default {
|
||||
name: 'AddOrUpdateTaskAllocationRuleData',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
doctorUserList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
selectList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
IdList: [],
|
||||
MedicalManagerUserId: null,
|
||||
TaskOptType: 1
|
||||
},
|
||||
rules: {
|
||||
MedicalManagerUserId: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }],
|
||||
},
|
||||
loading: false,
|
||||
btnLoading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.form.TrialId = this.$route.query.trialId
|
||||
this.form.IdList = Object.assign([], this.selectList.map(v => v.Id))
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
this.$refs.MedicalManagerDataForm.validate(valid => {
|
||||
console.log(valid)
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
assignMedicalReviewTask(this.form).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('保存成功')
|
||||
this.$emit('getList')
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
close() { this.$emit('close') }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,856 @@
|
|||
/* eslint-disable */
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:siteId')">
|
||||
<el-select v-model="searchData.SiteId" clearable filterable style="width:120px;">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
:key="'taskSearchData' + index"
|
||||
:label="item.TrialSiteCode"
|
||||
:value="item.SiteId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 受试者编号 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:table:subjectId')">
|
||||
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:seletctedReviews:title:ReadPeople')">
|
||||
<el-select v-model="searchData.DoctorUserId" clearable style="width:120px;">
|
||||
<el-option v-for="item of DoctorUserList" :key="'taskSearchData' + item.DoctorUserId" :value="item.DoctorUserId" :label="`${item.UserName}(${item.FullName})`" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="getList">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-edit-outline" v-hasPermi="['trials:trials-panel:reading:readTaskAllocation:edit']" @click="openAllocationConfigVisible">
|
||||
分配规则
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="btnLoading" v-hasPermi="['trials:trials-panel:reading:readTaskAllocation:edit']" @click="manualAllocation()">
|
||||
手动分配
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="btnLoading" @click="openAllocation('task')">
|
||||
访视/全局/肿瘤学阅片任务
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="btnLoading" @click="openAllocation('referee')">
|
||||
裁判阅片任务
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:70}"
|
||||
border
|
||||
:data="list"
|
||||
stripe
|
||||
@selection-change="handleSubjectAssignListSelectChange"
|
||||
>
|
||||
<el-table-column type="selection" align="left" width="45" />
|
||||
<el-table-column
|
||||
prop="TrialSiteCode"
|
||||
label="中心编号"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="受试者编号"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="VisitTaskTypeCount"
|
||||
label="访视"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="GlobalTaskTypeCount"
|
||||
label="全局"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="JudgeTaskTypeCount"
|
||||
label="裁判"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="OncologyTaskTypeCount"
|
||||
label="肿瘤学阅片"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="阅片人(R1)"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.NowDoctorUserList.length" style="display: flex;justify-content: left;align-items: center">
|
||||
<el-tag v-if="findDoctorUser(scope.row.NowDoctorUserList, 1).DoctorUser">
|
||||
{{ `${findDoctorUser(scope.row.NowDoctorUserList, 1).DoctorUser.UserName}(${findDoctorUser(scope.row.NowDoctorUserList, 1).DoctorUser.FullName})` }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="阅片人(R2)"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.NowDoctorUserList.length" style="display: flex;justify-content: left;align-items: center">
|
||||
<el-tag v-if="findDoctorUser(scope.row.NowDoctorUserList, 2).DoctorUser">
|
||||
{{ `${findDoctorUser(scope.row.NowDoctorUserList, 2).DoctorUser.UserName}(${findDoctorUser(scope.row.NowDoctorUserList, 2).DoctorUser.FullName})` }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="裁判(AD)"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.NowDoctorUserList.length" style="display: flex;justify-content: left;align-items: center">
|
||||
<el-tag v-if="findDoctorUser(scope.row.NowDoctorUserList, 3).DoctorUser">
|
||||
{{ `${findDoctorUser(scope.row.NowDoctorUserList, 3).DoctorUser.UserName}(${findDoctorUser(scope.row.NowDoctorUserList, 3).DoctorUser.FullName})` }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
label="肿瘤阅片人(O1)"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.NowDoctorUserList.length" style="display: flex;justify-content: left;align-items: center">
|
||||
<el-tag v-if="findDoctorUser(scope.row.NowDoctorUserList, 4).DoctorUser">
|
||||
{{ `${findDoctorUser(scope.row.NowDoctorUserList, 4).DoctorUser.UserName}(${findDoctorUser(scope.row.NowDoctorUserList, 4).DoctorUser.FullName})` }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label="操作"
|
||||
width="180"
|
||||
show-overflow-tooltip
|
||||
v-if="hasPermi(['trials:trials-panel:reading:readTaskAllocation:edit'])"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
:disabled="scope.row.NowDoctorUserList.length === 4"
|
||||
icon="el-icon-thumb"
|
||||
title="手动分配"
|
||||
@click="manualAllocation(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
:disabled="scope.row.NowDoctorUserList.length === 0"
|
||||
icon="el-icon-close"
|
||||
title="清除阅片人"
|
||||
@click="openClearAudience(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-document-copy"
|
||||
title="查看取消历史"
|
||||
@click="openSubjectCancelDoctorHistoryList(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination style="text-align: right;margin-top: 10px;" class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<!-- 详情 -->
|
||||
<el-dialog
|
||||
title="分配规则"
|
||||
:visible.sync="AllocationConfigVisible"
|
||||
width="1200px"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div class="base-dialog-body" style="position: relative;">
|
||||
<el-divider content-position="left" style="margin-bottom: 40px;">阅片人列表</el-divider>
|
||||
<el-form
|
||||
style="margin-top: 40px"
|
||||
ref="signForm"
|
||||
size="small"
|
||||
label-width="0px"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
border
|
||||
:data="TaskAllocationRuleList"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="DoctorUser.UserName"
|
||||
label="阅片人"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ `${scope.row.DoctorUser.UserName}(${scope.row.DoctorUser.FullName})` }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="PlanSubjectCount"
|
||||
label="计划受试者数量"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
label="阅片类型"
|
||||
min-width="280"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="item of scope.row.ReadingCategoryList">
|
||||
<el-tag v-if="item === 1" type="primary">{{ $fd('ReadingCategory', item) + '&' + $fd('ReadingCategory', 2) }}</el-tag>
|
||||
<el-tag v-if="item === 4" type="danger">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
<el-tag v-if="item === 5" type="warning">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
label="状态"
|
||||
min-width="80"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="!scope.row.IsEnable" type="danger">{{ $fd('IsEnable', scope.row.IsEnable) }}</el-tag>
|
||||
<el-tag v-else>{{ $fd('IsEnable', scope.row.IsEnable) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Note"
|
||||
label="备注"
|
||||
min-width="100"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
fixed="right"
|
||||
label="操作"
|
||||
width="180"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-edit-outline"
|
||||
title="编辑"
|
||||
@click="addOrEdit(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
<el-divider content-position="left">后续分配规则</el-divider>
|
||||
<el-descriptions class="margin-top" :column="1">
|
||||
<el-descriptions-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="TrialTaskInfo.IsFollowVisitAutoAssign" disabled>同一病例随访阅片任务自动分配(在拟分配的阅片人未标记为退出项目状态时)默认状态 {{$fd('AutoAssignDefaultState', TrialTaskInfo.FollowVisitAutoAssignDefaultState)}} </el-checkbox>
|
||||
</template>
|
||||
<div style="margin-left: 10px;">
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同一病例随访阅片任务自动分配(在拟分配的阅片人未标记为退出项目状态时)">
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="TrialTaskInfo.IsFollowGlobalVisitAutoAssign" disabled>同一病例全局任务自动分配(在拟分配的阅片人未标记为退出项目状态时 默认状态 {{$fd('AutoAssignDefaultState', TrialTaskInfo.FollowGlobalVisitAutoAssignDefaultState)}} </el-checkbox>
|
||||
</template>
|
||||
<div style="margin-left: 10px;">
|
||||
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template slot="label">
|
||||
<el-checkbox v-model="TrialTaskInfo.IsFollowJudgeTaskAutoAssign" disabled>同一病例第二次裁判任务自动分配(在拟分配的阅片人未标记为退出项目状态时)默认状态 {{$fd('AutoAssignDefaultState', TrialTaskInfo.FollowJudgeTaskAutoAssignDefaultState)}} </el-checkbox>
|
||||
</template>
|
||||
<div style="margin-left: 10px;" />
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleCancel"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="taskAllocationRuleVisible"
|
||||
:title="title"
|
||||
:visible.sync="taskAllocationRuleVisible"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<AddOrEditTaskAllocationRule :data="rowData" :TaskAllocationRuleList="TaskAllocationRuleList" :doctor-user-list="DoctorUserList" @close="() => {taskAllocationRuleVisible = false}" @getList="openAllocationConfigVisible" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="manualAllocationVisible"
|
||||
title="分配阅片人"
|
||||
:visible.sync="manualAllocationVisible"
|
||||
width="1580px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<ManualAllocationTable :data="rowData" :reading-type="ReadingType" :SubjectAssignSelectList="SubjectAssignSelectList" @close="() => {manualAllocationVisible = false}" @getList="getList"></ManualAllocationTable>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="ClearAudienceVisible"
|
||||
title="清除阅片人"
|
||||
:visible.sync="ClearAudienceVisible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<ClearAudienceList :data="rowData" :reading-type="ReadingType" @close="() => {ClearAudienceVisible = false}" @getList="getList"></ClearAudienceList>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="AllocationVisible"
|
||||
:title="AllocationType === 'task' ? ' 访视/全局/肿瘤学阅片任务' : ' 裁判阅片任务'"
|
||||
:visible.sync="AllocationVisible"
|
||||
:fullscreen="true"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<taskAllacation v-if="AllocationType === 'task'"></taskAllacation>
|
||||
<refereeAllacation v-else></refereeAllacation>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="SubjectCancelDoctorHistoryVisible"
|
||||
title="取消历史"
|
||||
:visible.sync="SubjectCancelDoctorHistoryVisible"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-table
|
||||
border
|
||||
:data="SubjectCancelDoctorHistoryList"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="CreateTime"
|
||||
label="取消时间"
|
||||
width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="Note"
|
||||
label="原因"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getTrialSiteSelect } from '@/api/trials'
|
||||
import { getSubjectCancelDoctorHistoryList, getSubjectAssignAndTaskStatList, getDoctorPlanAllocationRuleList, getSubjectApplyDoctorTaskStatList, assignSubjectTaskToDoctor, manualAssignDoctorApplyTask, autoSubjectAssignDoctor, getTaskAllocationRuleList, getSubjectAssignList, assignSubjectDoctor, cancelSubjectAssignDoctor, deleteTaskAllocationRule, configTrialTaskInfo, getDoctorUserSelectList } from '@/api/trials/reading'
|
||||
import AddOrEditTaskAllocationRule from './components/AddOrEditTaskAllocationRule'
|
||||
import ManualAllocationTable from './components/ManualAllocationTable'
|
||||
import ClearAudienceList from './components/ClearAudienceList'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import taskAllacation from '../task-allocation/index'
|
||||
import refereeAllacation from '../referee-allocation/index'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
DoctorUserId: null,
|
||||
IsHaveAssigned: null,
|
||||
IsAssignConfirmed: null
|
||||
}
|
||||
}
|
||||
const taskSearchDataDefault = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: true,
|
||||
SortField: '',
|
||||
TrialId: null,
|
||||
SiteId: null,
|
||||
SubjectId: null,
|
||||
SubjectCode: null,
|
||||
IsUrgent: null,
|
||||
TaskName: null,
|
||||
TaskState: null,
|
||||
DoctorUserId: null,
|
||||
ReadingCategory: null,
|
||||
TaskAllocationState: null,
|
||||
BeginAllocateDate: null,
|
||||
EndAllocateDate: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'TrialsNotice',
|
||||
components: { BaseContainer, Pagination, AddOrEditTaskAllocationRule, ManualAllocationTable, ClearAudienceList, taskAllacation, refereeAllacation },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
taskSearchData: taskSearchDataDefault(),
|
||||
maxLength: 0,
|
||||
list: [],
|
||||
siteOptions: [],
|
||||
total: 0,
|
||||
SubjectAssignListTotal: 0,
|
||||
loading: false,
|
||||
AllocationVisible: false,
|
||||
AllocationConfigVisible: false,
|
||||
taskAllocationRuleVisible: false,
|
||||
AutoAlloctionVisible: false,
|
||||
ClearAudienceVisible: false,
|
||||
WaitApplyVisible: false,
|
||||
applyVisible: false,
|
||||
manualAllocationVisible: false,
|
||||
SubjectCancelDoctorHistoryVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
AllocationType: null,
|
||||
currentData: {},
|
||||
param: {},
|
||||
DoctorUserList: [],
|
||||
TaskAllocationRuleList: [],
|
||||
btnLoading: false,
|
||||
value: true,
|
||||
value1: true,
|
||||
TrialTaskInfo: {
|
||||
TrialId: null,
|
||||
TaskAllocateObjEnum: 0,
|
||||
FollowVisitAutoAssignDefaultState: 0,
|
||||
FollowGlobalVisitAutoAssignDefaultState: 0,
|
||||
TaskAllocateDefaultState: 1,
|
||||
IsFollowVisitAutoAssign: true,
|
||||
IsFollowGlobalVisitAutoAssign: true
|
||||
},
|
||||
ReadingType: null,
|
||||
rules: {
|
||||
DoctorUserId: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }]
|
||||
},
|
||||
title: '',
|
||||
rowData: {},
|
||||
ApplyTaskInfo: {},
|
||||
timeList: [],
|
||||
WaitApplyList: [],
|
||||
SubjectAssignList: [],
|
||||
SubjectAssignSelectList: [],
|
||||
TaskAllocationRuleSelectList: [],
|
||||
readVisible: false,
|
||||
TaskOptType: null,
|
||||
OtherInfo: null,
|
||||
SubjectCancelDoctorHistoryList: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getDoctorUserSelectList()
|
||||
this.getSite()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
openSubjectCancelDoctorHistoryList(row) {
|
||||
getSubjectCancelDoctorHistoryList(row.SubjectId).then((res) => {
|
||||
this.SubjectCancelDoctorHistoryVisible = true
|
||||
this.SubjectCancelDoctorHistoryList = res.Result
|
||||
})
|
||||
},
|
||||
openAllocation(AllocationType) {
|
||||
this.AllocationVisible = true
|
||||
this.AllocationType = AllocationType
|
||||
},
|
||||
openClearAudience(row) {
|
||||
this.rowData = {...row}
|
||||
this.ClearAudienceVisible = true
|
||||
},
|
||||
findDoctorUser(list, type) {
|
||||
var a
|
||||
if (list.length > 0) {
|
||||
a = list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) ? list.find(v => {
|
||||
return v.ArmEnum === type
|
||||
}) : {
|
||||
DoctorUser: null
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
assignSubjectTaskToDoctor(row, type) {
|
||||
this.rowData = { ...row }
|
||||
this.rowData.TaskOptType = type
|
||||
if (type === 1 || type === 2) {
|
||||
this.readVisible = true
|
||||
} else if (type === 3) {
|
||||
this.$confirm('是否确定分配').then(() => {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(res => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
} else if (type === 4) {
|
||||
this.$confirm('是否确定取消分配').then(() => {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(res => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
assignSubjectTaskToDoctorSave() {
|
||||
this.$refs.readDataForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.rowData)
|
||||
assignSubjectTaskToDoctor(params).then(res => {
|
||||
this.$message.success('保存成功')
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.readVisible = false
|
||||
this.getList()
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
manualAssignDoctorApplyTaskSave() {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
manualAssignDoctorApplyTask(this.ApplyTaskInfo).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('生效成功')
|
||||
this.WaitApplyVisible = false
|
||||
this.getList()
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
manualAssignDoctorApplyTask(row) {
|
||||
var params = {
|
||||
TrialId: this.trialId,
|
||||
SubjectIdList: Object.assign([], this.SubjectAssignSelectList.map(v => v.SubjectId))
|
||||
}
|
||||
this.ApplyTaskInfo = {
|
||||
TrialId: this.trialId,
|
||||
SubjectDoctorUserList: Object.assign([], this.SubjectAssignSelectList.map(v => {
|
||||
v.DoctorUserIdArmList = v.DoctorUserList
|
||||
return v
|
||||
}))
|
||||
}
|
||||
if (row) {
|
||||
params.SubjectIdList = [row.SubjectId]
|
||||
var param = Object.assign({}, row)
|
||||
param.DoctorUserIdArmList = param.DoctorUserList
|
||||
this.ApplyTaskInfo = Object.assign({}, row)
|
||||
delete this.ApplyTaskInfo.DoctorUserList
|
||||
delete this.ApplyTaskInfo.DoctorUserIdList
|
||||
this.ApplyTaskInfo.SubjectDoctorUserList = [
|
||||
param
|
||||
]
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
getSubjectApplyDoctorTaskStatList(params).then(res => {
|
||||
if (res.Result.length === 0) {
|
||||
this.$message.error('该项目没有有效阅片人')
|
||||
return
|
||||
}
|
||||
this.WaitApplyList = res.Result
|
||||
this.WaitApplyVisible = true
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
autoSubjectAssignDoctor() {
|
||||
this.$confirm('确定执行自动分配?').then(() => {
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
autoSubjectAssignDoctor({ TrialId: this.trialId }).then(res => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.$message.success('自动分配成功')
|
||||
this.getList()
|
||||
this.openAutoAlloction()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSaveTaskAllocationRuleSelectList() {
|
||||
if (this.TaskAllocationRuleSelectList.length === 0) {
|
||||
this.$message.error('请选择阅片人')
|
||||
return
|
||||
}
|
||||
var num
|
||||
if (this.ReadingType === 2) {
|
||||
num = 2
|
||||
} else {
|
||||
num = 1
|
||||
}
|
||||
if (this.TaskAllocationRuleSelectList.length !== num) {
|
||||
this.$message.error(`当前阅片模式为${this.$fd('ReadingMethod', this.ReadingType)},请选择正确阅片人数量`)
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
DoctorUserIdArmList: this.TaskAllocationRuleSelectList.map((v, i) => { return { DoctorUserId: v.DoctorUserId, ArmEnum: this.ReadingType === 1 ? 1 : i + 1 } }),
|
||||
SubjectIdList: this.SubjectAssignSelectList.map(v => v.SubjectId),
|
||||
TrialId: this.trialId,
|
||||
IsReAssign: true
|
||||
}
|
||||
assignSubjectDoctor(params).then(v => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
this.openAutoAlloction()
|
||||
this.TaskAllocationRuleSelectList = []
|
||||
this.SubjectAssignSelectList = []
|
||||
this.getDoctorUserSelectList()
|
||||
this.$message.success('分配成功')
|
||||
this.manualAllocationVisible = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
selectable(row) {
|
||||
var num
|
||||
if (this.ReadingType === 2) {
|
||||
num = 2
|
||||
} else {
|
||||
num = 1
|
||||
}
|
||||
if (this.TaskAllocationRuleSelectList.length === num && !this.TaskAllocationRuleSelectList.find(v => { return v.UserName === row.UserName })) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
manualAllocation(row) {
|
||||
this.rowData = {}
|
||||
if (row) {
|
||||
this.rowData = { ...row }
|
||||
this.SubjectAssignSelectList = [row]
|
||||
}
|
||||
if (this.SubjectAssignSelectList.length === 0) {
|
||||
this.$message.error('请勾选要分配的受试者')
|
||||
return
|
||||
}
|
||||
this.manualAllocationVisible = true
|
||||
},
|
||||
handleTaskAllocationRuleListSelectChange(e) {
|
||||
this.TaskAllocationRuleSelectList = e
|
||||
},
|
||||
handleSubjectAssignListSelectChange(e) {
|
||||
this.SubjectAssignSelectList = e
|
||||
},
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
this.searchData.BeginAllocateDate = this.timeList[0]
|
||||
this.searchData.EndAllocateDate = this.timeList[1]
|
||||
} else {
|
||||
this.searchData.BeginAllocateDate = null
|
||||
this.searchData.EndAllocateDate = null
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
this.AllocationConfigVisible = false
|
||||
},
|
||||
handleSave() {
|
||||
this.btnLoading = true
|
||||
this.loading = true
|
||||
var params = Object.assign({}, this.TrialTaskInfo)
|
||||
params.TrialId = this.$route.query.trialId
|
||||
configTrialTaskInfo(params).then(res => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
this.AllocationConfigVisible = false
|
||||
this.getList()
|
||||
this.$message.success('保存成功')
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm(`确定要删除${row.DoctorUser.UserName}(${row.DoctorUser.FullName})的任务分配规则?`, {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}).then(() => {
|
||||
this.loading = true
|
||||
deleteTaskAllocationRule(row.Id, false).then(res => {
|
||||
this.loading = false
|
||||
this.$message.success('删除成功')
|
||||
this.openAllocationConfigVisible()
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
addOrEdit(row) {
|
||||
if (row) {
|
||||
this.rowData = { ...row }
|
||||
this.title = '编辑'
|
||||
} else {
|
||||
this.rowData = {}
|
||||
this.title = '新增'
|
||||
}
|
||||
this.taskAllocationRuleVisible = true
|
||||
},
|
||||
openAllocationConfigVisible() {
|
||||
this.loading = true
|
||||
getDoctorPlanAllocationRuleList({
|
||||
TrialId: this.$route.query.trialId
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.TaskAllocationRuleList = res.Result
|
||||
this.TrialTaskInfo = Object.assign({}, res.OtherInfo)
|
||||
this.AllocationConfigVisible = true
|
||||
this.taskAllocationRuleVisible = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
openAutoAlloction() {
|
||||
this.loading = true
|
||||
getTaskAllocationRuleList({
|
||||
TrialId: this.$route.query.trialId
|
||||
}).then(async(res) => {
|
||||
this.taskSearchData.TrialId = this.$route.query.trialId
|
||||
var params = Object.assign({}, this.taskSearchData)
|
||||
var SubjectAssignListRes = await getSubjectAssignList(params)
|
||||
this.SubjectAssignList = SubjectAssignListRes.Result.CurrentPageData
|
||||
this.SubjectAssignListTotal = SubjectAssignListRes.Result.TotalCount
|
||||
this.loading = false
|
||||
this.TaskAllocationRuleList = res.Result
|
||||
this.TrialTaskInfo = Object.assign({}, res.OtherInfo)
|
||||
this.AutoAlloctionVisible = true
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getDoctorUserSelectList() {
|
||||
getDoctorUserSelectList(this.$route.query.trialId).then(res => {
|
||||
this.DoctorUserList = res.Result
|
||||
if (this.DoctorUserList.length > 0) {
|
||||
this.ReadingType = this.DoctorUserList[0].ReadingType
|
||||
} else {
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.loading = true
|
||||
getSubjectAssignAndTaskStatList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.OtherInfo = res.OtherInfo
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.manualAllocationVisible = false
|
||||
this.ClearAudienceVisible = false
|
||||
this.SubjectAssignSelectList = []
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
handleReset2() {
|
||||
this.taskSearchData = taskSearchDataDefault()
|
||||
this.openAutoAlloction()
|
||||
},
|
||||
getSite() {
|
||||
getTrialSiteSelect(this.trialId).then(res => {
|
||||
this.siteOptions = res.Result
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
>>>.hidden-row{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-dialog__body {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
>>>.el-tag--danger.el-tag--dark {
|
||||
// background-color: #f56c6c!important;
|
||||
border-color: none!important;
|
||||
// color: #fff!important;
|
||||
}
|
||||
>>>#TaskAllocationRuleList thead .el-checkbox__inner{
|
||||
display: none;
|
||||
}
|
||||
>>>.el-descriptions-item__label.has-colon:after{
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,364 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="chat-wrapper">
|
||||
<div class="chat-content">
|
||||
<div v-for="(record,index) in recordContent" :key="index">
|
||||
<div :class="[!record.IsCurrentUser?'word':'word-my']">
|
||||
<img v-if="record.UserTypeEnumInt*1 === 14" :src="mimAvatar" alt="MIM">
|
||||
<img v-else :src="irAvatar" alt="IR">
|
||||
<div class="info">
|
||||
<p class="user-info">
|
||||
<span style="font-weight:700;">{{ record.CreateUserName }} </span>
|
||||
<span>({{ record.CreateTime }}) </span>
|
||||
</p>
|
||||
<div class="info-content">
|
||||
<template v-if="record.UserTypeEnumInt === 14 && record.Content">
|
||||
<div v-if="record.MedicalDialogCloseEnum!== null">
|
||||
{{ $t('trials:medicalFeedback:title:closeReasonEnum') }} {{ $fd('MedicalDialogCloseEnum',record.MedicalDialogCloseEnum) }}
|
||||
</div>
|
||||
<div>{{ record.Content }}</div>
|
||||
</template>
|
||||
<template v-else-if="record.UserTypeEnumInt === 14 && !record.Content">
|
||||
<div>
|
||||
<!-- 您好,根据医学审核反馈,该阅片任务的评估有如下问题需要您确认或澄清: -->
|
||||
{{ $t('trials:medicalFeedback:message:msg1') }}
|
||||
<ol>
|
||||
{{ record.Questioning }}
|
||||
</ol>
|
||||
</div>
|
||||
<div v-if="record.FileList && record.FileList.length > 0" style="margin-top:5px;">
|
||||
<!-- 本次医学审核相关截图(如适用)如下: -->
|
||||
{{ $t('trials:medicalFeedback:message:msg2') }}
|
||||
<ol>
|
||||
<li v-for="file in record.FileList" :key="file.ImagePath" style="list-style: none;">
|
||||
<el-button
|
||||
type="text"
|
||||
size="mini"
|
||||
@click="previewImage(file.ImagePath)"
|
||||
>{{ file.FileName }}</el-button>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div style="margin-top:5px;">
|
||||
<!-- 根据本项目《独立影像评估章程》的相关约定,该类问题医学审核建议为: -->
|
||||
{{ $t('trials:medicalFeedback:message:msg3') }}
|
||||
<ol>
|
||||
<span style="color:red">{{ $fd('AuditAdvice', record.AuditAdviceEnum) }}</span>
|
||||
</ol>
|
||||
</div>
|
||||
<div style="margin-top:5px;">
|
||||
<!-- 为高效解决/处理以上全部医学反馈问题,麻烦您在对该阅片任务的评估准确复核后,明确是否认可医学反馈问题及结论。如不认可医学反馈,请逐条准确完整回复不认可的原因,非常感谢。 -->
|
||||
{{ $t('trials:medicalFeedback:message:msg4') }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div>
|
||||
{{ $t('trials:medicalFeedback:title:isEndorse') }}{{ $fd('MedicalReviewDoctorUserIdea', record.DoctorUserIdeaEnum) }}
|
||||
</div>
|
||||
<div v-if="record.DoctorUserIdeaEnum===2"> {{ $t('trials:medicalFeedback:title:reason') }}{{ record.DisagreeReason }}</div>
|
||||
<div v-if="record.MedicalDialogCloseEnum!== null">
|
||||
<!-- 是否申请重阅: -->
|
||||
{{ $t('trials:medicalFeedback:title:isRequestReread') }}{{ $fd('YesOrNo', record.IsApplyHeavyReading) }}
|
||||
</div>
|
||||
<div v-if="record.FileList && record.FileList.length > 0" style="margin-top:5px;">
|
||||
<!-- 本次医学审核相关截图(如适用)如下: -->
|
||||
{{ $t('trials:medicalFeedback:message:msg5') }}
|
||||
<ol>
|
||||
<li v-for="file in record.FileList" :key="file.ImagePath" style="list-style: none;">
|
||||
<el-button
|
||||
type="text"
|
||||
size="mini"
|
||||
@click="previewImage(file.ImagePath)"
|
||||
>{{ file.FileName }}</el-button>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="otherInfo && !otherInfo.IsClosedDialog && userTypeEnumInt === 14"
|
||||
class="chat-message"
|
||||
>
|
||||
<div class="message">
|
||||
<el-input
|
||||
v-model="newMessage"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
/>
|
||||
</div>
|
||||
<div class="function">
|
||||
<!-- 回复 -->
|
||||
<el-button
|
||||
:disabled="newMessage===''"
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="handleReply"
|
||||
>
|
||||
{{ $t('trials:medicalFeedback:button:reply') }}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="otherInfo && !otherInfo.IsClosedDialog && userTypeEnumInt === 13" class="chat-message">
|
||||
<div class="function">
|
||||
<!-- 回复 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="handleIRReply"
|
||||
>
|
||||
{{ $t('trials:medicalFeedback:button:reply') }}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:visible.sync="previewDialog"
|
||||
width="600px"
|
||||
>
|
||||
<!-- <img width="100%" :src="imagePath" alt="图片未找到"> -->
|
||||
<el-image :src="imagePath" width="100%">
|
||||
<div slot="placeholder" class="image-slot">
|
||||
{{ $t('trials:medicalFeedback:message:loading') }}<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-if="irFeedbackForm.visible"
|
||||
:visible.sync="irFeedbackForm.visible"
|
||||
:close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper"
|
||||
:title="irFeedbackForm.title"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
>
|
||||
<FeedbackForm
|
||||
:task-medical-review-id="taskMedicalReviewId"
|
||||
:visit-task-id="visitTaskId"
|
||||
@getList="getMessageList"
|
||||
@close="irFeedbackForm.visible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getMedicalReviewDialog, sendMedicalReviewDialog } from '@/api/trials'
|
||||
import FeedbackForm from '@/views/trials/trials-panel/reading/medical-feedback/components/FeedbackForm'
|
||||
import mimAvatar from '@/assets/MIM.png'
|
||||
import irAvatar from '@/assets/IR.png'
|
||||
export default {
|
||||
name: 'ChatForm',
|
||||
components: {
|
||||
FeedbackForm
|
||||
},
|
||||
props: {
|
||||
taskMedicalReviewId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
recordContent: [],
|
||||
newMessage: '',
|
||||
showNewMessage: false,
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
userId: zzSessionStorage.getItem('userId'),
|
||||
mimAvatar,
|
||||
irAvatar,
|
||||
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
||||
ReuploadEnum: 0,
|
||||
trialId: this.$route.query.trialId,
|
||||
currentUserId: zzSessionStorage.getItem('userId'),
|
||||
otherInfo: {},
|
||||
previewDialog: false,
|
||||
imagePath: '',
|
||||
irFeedbackForm: { visible: false, title: '' }
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getMessageList()
|
||||
},
|
||||
methods: {
|
||||
// 初始化聊天信息
|
||||
getMessageList() {
|
||||
this.loading = true
|
||||
var param = {
|
||||
taskMedicalReviewId: this.taskMedicalReviewId
|
||||
}
|
||||
getMedicalReviewDialog(param).then(res => {
|
||||
this.otherInfo = res.OtherInfo
|
||||
this.recordContent = res.Result
|
||||
this.setScrollHeight()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
setScrollHeight() {
|
||||
setTimeout(() => {
|
||||
var container = document.querySelectorAll('.chat-content')[0]
|
||||
container.scrollTop = container.scrollHeight
|
||||
}, 100)
|
||||
},
|
||||
// 回复质疑
|
||||
handleReply() {
|
||||
if (!this.newMessage) return
|
||||
var param = {
|
||||
taskMedicalReviewId: this.taskMedicalReviewId,
|
||||
content: this.newMessage
|
||||
}
|
||||
this.loading = true
|
||||
sendMedicalReviewDialog(param).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.newMessage = ''
|
||||
this.getMessageList()
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
previewImage(path) {
|
||||
this.imagePath = `/api/${path}`
|
||||
this.previewDialog = true
|
||||
},
|
||||
handleIRReply() {
|
||||
// '反馈'
|
||||
this.irFeedbackForm.title = this.$t('trials:medicalFeedback:title:feedback')
|
||||
|
||||
this.irFeedbackForm.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.chat-wrapper{
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.chat-content{
|
||||
width:100%;
|
||||
padding: 20px;
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
.word{
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
img{
|
||||
width:40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.info{
|
||||
margin-left: 10px;
|
||||
.user-info{
|
||||
font-size: 12px;
|
||||
color:rgba(51,51,51,0.8);
|
||||
margin:0;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.info-content{
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
background-color: #ebeef5;
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.info-content::before{
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
top: 8px;
|
||||
content: '';
|
||||
border-right: 10px solid #ebeef5;
|
||||
border-top: 8px solid transparent;
|
||||
border-bottom: 8px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
.word-my{
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: row-reverse;
|
||||
margin-bottom: 20px;
|
||||
img{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.info{
|
||||
width: 90%;
|
||||
margin-left: 10px;
|
||||
text-align: right;
|
||||
.user-info{
|
||||
font-size: 12px;
|
||||
color: rgba(51,51,51,0.8);
|
||||
margin: 0;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: -5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.info-content{
|
||||
position: relative;
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
margin-top: 8px;
|
||||
background-color: #7574d9;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
.info-content::after{
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: 8px;
|
||||
content: '';
|
||||
border-left: 10px solid #7574d9;
|
||||
border-top: 8px solid transparent;
|
||||
border-bottom: 8px solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.chat-message{
|
||||
padding: 0 50px;
|
||||
.function{
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
ol{
|
||||
margin: 5px;
|
||||
padding: 0px 10px;
|
||||
counter-reset: num;
|
||||
li{
|
||||
counter-increment: num;
|
||||
// list-style:none;
|
||||
}
|
||||
}
|
||||
ol.example{counter-reset: num;}
|
||||
ol.example li{counter-increment: num; list-style:none;}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,68 @@
|
|||
/* eslint-disable */
|
||||
export default {
|
||||
'components:uploadvideo:message:xf1': `上传成功`,
|
||||
'components:uploadvideo:message:xf2': `选择的视频不能在浏览器环境播放,请点击转码,等待转码成功之后再进行上传操作`,
|
||||
'components:uploadvideo:message:xf3': `页面未在安全上下文中,不能进行转码,请联系开发人员配置SSL证书`,
|
||||
'components:uploadvideo:message:xf4': `nginx未设置同源隔离,不能进行转码,请联系开发人员配置Nginx请求头`,
|
||||
'components:uploadvideo:message:xf5': `开始转码,请勿关闭窗口或页面`,
|
||||
'components:uploadvideo:message:xf6': `转码成功`,
|
||||
'components:uploadvideo:message:xf7': `文件读取成功,请上传`,
|
||||
'passwordReset:form:passwordCentent': `密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)`,
|
||||
'trials:uploadNonDicoms:action:xfuploadvideo': `上传视频文件`,
|
||||
'trials:uploadNonDicoms:title:xfuploadvideo': `上传视频文件`,
|
||||
'trials:uploadNonDicoms:title:xflookvideo': `查看视频文件`,
|
||||
'trials:check:radio:passreason1': `线上质疑解决核查通过`,
|
||||
'trials:check:radio:passreason2': `线下核查通过`,
|
||||
'trials:check:radio:passreason3': `实时阅片跳过核查`,
|
||||
'trials:check:radio:passreason4': `其它`,
|
||||
'trials:check:radio:closereason1': `问题已解决`,
|
||||
'trials:check:radio:closereason2': `问题无法解决强制关闭质疑`,
|
||||
'trials:check:radio:closereason3': `其他`,
|
||||
'trials:qcQuality:label:passReason': `通过原因`,
|
||||
'trials:qcQuality:label:closeReason': `关闭原因`,
|
||||
'trials:consistencyCheck:dialogTitle:xfpassManually': `一致性核查通过`,
|
||||
'trials:consistencyCheck:dialogTitle:xfclose': `关闭一致性核查`,
|
||||
'recompose:form:email': `邮箱`,
|
||||
'recompose:form:role': `角色`,
|
||||
'trials:consistencyCheck:label:passreason': `原因`,
|
||||
'trials:consistencyCheck:label:closereason': `备注`,
|
||||
'trials:trials-panel:taskAllocation': `访视任务分配`,
|
||||
'trials:trials-panel:reading': `阅片`,
|
||||
'trials:trials-panel:refereeAllocation': `裁判任务分配`,
|
||||
'trials:trials-panel:readingTracking': `阅片跟踪`,
|
||||
'trials:trials-panel:reReadingTracking': `重阅跟踪`,
|
||||
'trials:trials-panel:tab:pmMedicalFeedback': `医学审核`,
|
||||
'trials:trials-panel:reading:consistency-analysis': `一致性分析`,
|
||||
'trials:trials-panel:attachments:reReadingTracking': `重阅审批`,
|
||||
'trials:trials-panel:message:notIsHasDicom': `当前文件夹没有DICOM文件,请检查文件夹是否正确!`,
|
||||
'trials:trials-panel:reading:readTaskAllocation': `阅片任务分配`,
|
||||
'trials:trials-panel:attachments:spm-enrollment': `阅片人筛选`,
|
||||
'trials:seletctedReviews:title:language': `语言`,
|
||||
'trials:enrolledReviews:button:sow': `既往阅片情况声明`,
|
||||
'trials:enrolledReviews:button:asow': `入项资格确认书`,
|
||||
'trials:enrolledReviews:button:tackNum': `任务量(未读/已读/总数)`,
|
||||
'DicomViewer:data:customWwc': `自定义调窗`,
|
||||
'CustomWwwcForm:form:label:ww': `窗宽`,
|
||||
'CustomWwwcForm:form:label:wl': `窗位`,
|
||||
'trials:trials-panel:readTaskAllocation:search:ReadPeople': `阅片人`,
|
||||
'trials:trials-panel:readTaskAllocation:button:AllocationRule': `分配规则`,
|
||||
'trials:trials-panel:readTaskAllocation:button:ManualDistribution': `手动分配`,
|
||||
'trials:trials-panel:readTaskAllocation:button:vgoTask': `访视/全局/肿瘤学阅片任务`,
|
||||
'trials:trials-panel:readTaskAllocation:button:adTask': `裁判阅片任务`,
|
||||
'trials:trials-panel:readTaskAllocation:table:TrialSiteCode': `中心编号`,
|
||||
'trials:trials-panel:readTaskAllocation:table:SubjectCode': `受试者编号`,
|
||||
'trials:trials-panel:readTaskAllocation:table:VisitTaskTypeCount': `访视`,
|
||||
'trials:trials-panel:readTaskAllocation:table:GlobalTaskTypeCount': `全局`,
|
||||
'trials:trials-panel:readTaskAllocation:table:JudgeTaskTypeCount': `裁判`,
|
||||
'trials:trials-panel:readTaskAllocation:table:OncologyTaskTypeCount': `肿瘤学阅片`,
|
||||
'trials:trials-panel:readTaskAllocation:table:R1': `阅片人(R1)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:R2': `阅片人(R2)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:AD': `裁判(AD)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:O1': `肿瘤阅片人(O1)`,
|
||||
'trials:trials-panel:readTaskAllocation:table:operation': `操作`,
|
||||
'trials:trials-panel:readTaskAllocation:table:ManualDistribution': `手动分配`,
|
||||
'trials:trials-panel:readTaskAllocation:table:clearReview': `清除阅片人`,
|
||||
'trials:trials-panel:readTaskAllocation:table:lookCancelHistory': `查看取消历史`,
|
||||
'trials:pendingReadingTasks:button:ExistReadingApply': `存在重阅申请(项目组申请 | 独立阅片人申请)还未处理完毕,当前标准未读任务不允许开始读片`,
|
||||
'trials:readingPeriod:dialogTitle:EditSubjectPR': `编辑阅片期`,
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;font-size: 15px;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
:label="`${language==='en'?question.QuestionEnName:question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: true,
|
||||
message: $t('common:ruleMessage:select'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group'?'mb':'']"
|
||||
>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
clearable
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-else-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<AssessmentFormItem
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'AssessmentFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
// console.log(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
Binary file not shown.
|
@ -0,0 +1,822 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<!-- <template slot="search-container">
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:enroll']"
|
||||
icon="el-icon-plus"
|
||||
type="primary"
|
||||
style="margin-left: auto"
|
||||
@click="handleEnroll"
|
||||
>Enroll</el-button>
|
||||
</template> -->
|
||||
|
||||
<template slot="main-container">
|
||||
<!-- 入组医生列表 -->
|
||||
<el-table
|
||||
ref="myTable"
|
||||
v-loading="listLoading"
|
||||
v-adaptive="{bottomOffset:55}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column type="index" width="40" />
|
||||
<!-- Name -->
|
||||
<el-table-column
|
||||
:label="$t('trials:enrolledReviews:table:name')"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
prop="FirstName"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<router-link
|
||||
style="color: #428bca;"
|
||||
tag="a"
|
||||
:to="{
|
||||
path: `/trialsResume?doctorId=${scope.row.DoctorId}&token=${token}`,
|
||||
}"
|
||||
target="_blank"
|
||||
>{{ scope.row.LastName }} / {{ scope.row.FirstName }}</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- Name CN -->
|
||||
<el-table-column
|
||||
prop="ChineseName"
|
||||
sortable="custom"
|
||||
:label="$t('trials:enrolledReviews:table:nameCN')"
|
||||
width="120"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 用户名 -->
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
:label="$t('trials:enrolledReviews:table:userName')"
|
||||
width="150"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 入组时间 -->
|
||||
<el-table-column
|
||||
prop="EnrollTimeStr"
|
||||
:label="$t('trials:enrolledReviews:table:enrollmentTime')"
|
||||
width="200"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.EnrollTime">
|
||||
{{ `${scope.row.EnrollTime}` }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="EnrollTimeStr"
|
||||
:label="$t('trials:enrolledReviews:table:status')"
|
||||
width="100"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
<el-switch
|
||||
v-model="scope.row.IsEnable"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
@change="(v) => {return isEnableChange(scope.row, v)}"
|
||||
/>
|
||||
<span>{{$fd('IsEnable', scope.row.IsEnable)}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="ite of TrialReadingCriterionList"
|
||||
:label="ite.TrialReadingCriterionName"
|
||||
width="360"
|
||||
header-align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column
|
||||
:label="$t('trials:enrolledReviews:table:readingType')"
|
||||
width="300"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="item of scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}) ? scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).ReadingCategorys : []">
|
||||
<el-tag v-if="item === 1" type="primary">{{ $fd('ReadingCategory', item) + ' & ' + $fd('ReadingCategory', 2) }}</el-tag>
|
||||
<!-- <el-tag v-if="item === 2" type="info">{{ $fd('ReadingCategory', item) }}</el-tag>-->
|
||||
<el-tag v-if="item === 4" type="danger">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
<el-tag v-if="item === 5" type="warning">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
</span>
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
type="text"
|
||||
@click="openSetEnrollReadingCategory(scope.row, ite.TrialReadingCriterionId)"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:config') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('trials:enrolledReviews:message:SOW')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).StatementCriterionFileList.length > 0">
|
||||
<el-button type="text" @click="windowOpen(scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).StatementCriterionFileList[0].FilePath)">View</el-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>{{ $t('trials:enrolledReviews:label:notUpload') }}</span>
|
||||
<!-- 上传 -->
|
||||
<el-button
|
||||
v-if="ite.CriterionType === 0"
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
type="text"
|
||||
style="margin-left: 10px"
|
||||
@click="addCol(0, scope.row, ite, $t('trials:enrolledReviews:message:SOW'))"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:upload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('trials:enrolledReviews:message:EQC')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).AcknowledgementCriterionFileList.length > 0">
|
||||
<el-button type="text" @click="windowOpen(scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).AcknowledgementCriterionFileList[0].FilePath)">View</el-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>{{ $t('trials:enrolledReviews:label:notUpload') }}</span>
|
||||
<!-- 上传 -->
|
||||
<el-button
|
||||
v-if="ite.CriterionType === 0"
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
type="text"
|
||||
style="margin-left: 10px"
|
||||
@click="addCol(1, scope.row, ite, $t('trials:enrolledReviews:message:SOW'))"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:upload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('trials:enrolledReviews:button:tackNum')"
|
||||
width="300"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).PendingCount }}
|
||||
/
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).ComplectedCount }}
|
||||
/
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).TotalCount }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<!-- 上传SOW -->
|
||||
<base-model :config="sow_model">
|
||||
<template slot="dialog-body">
|
||||
<upload-acksow
|
||||
ref="uploadAckSow"
|
||||
:trial-id="listQuery.TrialId"
|
||||
:doctor-id="doctorId"
|
||||
@getFileList="getFileList"
|
||||
/>
|
||||
</template>
|
||||
</base-model>
|
||||
|
||||
<!-- 修改 Reading Type -->
|
||||
<base-model :config="readingType_model">
|
||||
<template slot="dialog-body">
|
||||
<!-- Reading Type -->
|
||||
<label>{{ $t('trials:enrolledReviews:table:readingType') }}: </label>
|
||||
<el-select
|
||||
v-model="readingType"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
style="width: 70%"
|
||||
>
|
||||
<el-option :value="0" label="TP&GL&AD" />
|
||||
<el-option :value="1" label="TP&GL" />
|
||||
<el-option :value="2" label="AD" />
|
||||
</el-select>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
:disabled="readingType_model.btnLoading"
|
||||
type="primary"
|
||||
@click="readingType_model.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="readingType_model.btnLoading"
|
||||
@click="handleUpdateReadingType"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
<!-- 修改 readingCategory -->
|
||||
<base-model :config="readingCategory_model">
|
||||
<template slot="dialog-body">
|
||||
<!-- Reading Type -->
|
||||
<label>{{ $t('trials:enrolledReviews:table:readingType') }}: </label>
|
||||
<el-select
|
||||
v-model="ReadingCategorys"
|
||||
filterable
|
||||
allow-create
|
||||
multiple
|
||||
default-first-option
|
||||
style="width: 70%"
|
||||
>
|
||||
<el-option v-for="item of $d.ReadingCategory" v-if="item.value === 1" :key="item.id" :value="1" :label="$fd('ReadingCategory', 1) + ' & ' + $fd('ReadingCategory', 2)" />
|
||||
<el-option v-for="item of $d.ReadingCategory" v-if="item.value === 4 && IsArbitrationReading" :key="item.id" :value="item.value" :label="$fd('ReadingCategory', 4)" />
|
||||
<el-option v-for="item of $d.ReadingCategory" v-if="item.value === 5 && IsOncologyReading" :key="item.id" :value="item.value" :label="$fd('ReadingCategory', 5)" />
|
||||
</el-select>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
:disabled="readingCategory_model.btnLoading"
|
||||
type="primary"
|
||||
@click="readingCategory_model.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="readingCategory_model.btnLoading"
|
||||
@click="handleUpdateReadingCategory"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
<!-- 修改医生状态 -->
|
||||
<base-model :config="reviewerStatus_model">
|
||||
<template slot="dialog-body">
|
||||
<el-form
|
||||
ref="updateStatusForm"
|
||||
:model="updateStatusForm"
|
||||
:rules="updateStatusFormrules"
|
||||
>
|
||||
<el-form-item :label="$t('trials:enrolledReviews:label:enrollmentStatus')" prop="Status">
|
||||
<el-select
|
||||
v-model="updateStatusForm.Status"
|
||||
style="width:60%;"
|
||||
>
|
||||
<!-- 0:回退;1:出组; -->
|
||||
<el-option v-for="item of $d.OutOrInEnrollment" :key="`OutOrInEnrollment${item.value}`" :value="item.value" :label="item.label" :disabled="item.value === 0 && currentWorkload>0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="updateStatusForm.Status== 1"
|
||||
:label="$t('trials:enrolledReviews:label:outOfEnrollmentTime')"
|
||||
prop="OutEnrollmentTime"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="updateStatusForm.OutEnrollmentTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
format="yyyy-MM-dd"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
:disabled="reviewerStatus_model.btnLoading"
|
||||
type="primary"
|
||||
@click="reviewerStatus_model.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="reviewerStatus_model.btnLoading"
|
||||
@click="handleUpdateReviewerStatus"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
<BaseModel :config="model_cfg">
|
||||
<template slot="dialog-body">
|
||||
<el-form
|
||||
ref="DictionaryTypeConfigForm"
|
||||
:model="form"
|
||||
label-width="120px"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item label="Criterion Type " prop="CriterionType">
|
||||
<el-input v-model="form.CriterionName" disabled />
|
||||
<!-- <el-select v-model="form.CriterionType">-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item of $d.CriterionType"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :value="item.value"-->
|
||||
<!-- :label="item.label"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="File" prop="FilePath">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview2"
|
||||
:on-remove="handleRemoveFile2"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
:file-list="fileList"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="fileList.length > 0">点击上传</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
|
||||
</template>
|
||||
</BaseModel>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getTrialEnrollmentWorkloadStats,
|
||||
deleteReviewerAckSOW,
|
||||
updateReviewerReadingType,
|
||||
enrollBackOrOut,
|
||||
setEnrollReadingCategory
|
||||
} from '@/api/trials'
|
||||
import { addDoctorCriterionFile } from '@/api/reviewers'
|
||||
import { uploadFile } from '@/api/attachment'
|
||||
import { updateTrialReviewerState } from '@/api/trials/reading'
|
||||
import UploadAcksow from './components/UploadAcksow'
|
||||
import store from '@/store'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import BaseModel from '@/components/BaseModel'
|
||||
export default {
|
||||
components: { UploadAcksow, BaseContainer, BaseModel },
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
TrialReadingCriterionId: null,
|
||||
listQuery: {
|
||||
TrialId: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 100,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
},
|
||||
doctorId: '',
|
||||
currentRow: {},
|
||||
listLoading: false,
|
||||
total: 0,
|
||||
trialId: '',
|
||||
currentClickRowData: '',
|
||||
btnLoading: false,
|
||||
readingType: '',
|
||||
model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true },
|
||||
sow_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:signedAckOfSow'),
|
||||
showClose: true,
|
||||
width: '500px'
|
||||
},
|
||||
readingType_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeReadingType'),
|
||||
showClose: true,
|
||||
width: '500px',
|
||||
btnLoading: false
|
||||
},
|
||||
readingCategory_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeReadingType'),
|
||||
showClose: true,
|
||||
width: '500px',
|
||||
btnLoading: false
|
||||
},
|
||||
reviewerStatus_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeStatus'),
|
||||
showClose: true,
|
||||
width: '500px',
|
||||
btnLoading: false
|
||||
},
|
||||
updateStatusForm: {
|
||||
Status: '',
|
||||
OutEnrollmentTime: ''
|
||||
},
|
||||
updateStatusFormrules: {
|
||||
Status: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }],
|
||||
OutEnrollmentTime: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }]
|
||||
},
|
||||
token: store.getters.token,
|
||||
ReadingCategorys: [],
|
||||
apiReadingCategorys: [],
|
||||
TrialReadingCriterionList: [],
|
||||
IsArbitrationReading: true,
|
||||
IsOncologyReading: true,
|
||||
fileList: [],
|
||||
form: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentWorkload() {
|
||||
if (Object.keys(this.currentRow).length === 0) return 0
|
||||
var total = this.currentRow.Adjudication + this.currentRow.AdjudicationIn24H + this.currentRow.AdjudicationIn48H + this.currentRow.Timepoint + this.currentRow.TimepointIn24H + this.currentRow.TimepointIn48H + this.currentRow.TrainingTimes + this.currentRow.RefresherTraining + this.currentRow.Global + this.currentRow.Downtime
|
||||
return total
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialCode
|
||||
this.listQuery.TrialId = this.$route.query.trialId
|
||||
this.initPage()
|
||||
},
|
||||
methods: {
|
||||
beforeUpload() {
|
||||
if (this.fileList.length > 0) {
|
||||
// 只允许上传1个文件
|
||||
this.$alert(this.$t('trials:enrolledReviews:message:uploadSowWaring1'))
|
||||
return
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs['DictionaryTypeConfigForm'].validate(valid => {
|
||||
if (!valid) return
|
||||
addDoctorCriterionFile(this.form).then(res => {
|
||||
// 保存成功
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.initPage()
|
||||
this.handleCancle()
|
||||
})
|
||||
})
|
||||
},
|
||||
handlePreview3(row) {
|
||||
if (row.FilePath) {
|
||||
window.open(row.FilePath, '_blank')
|
||||
}
|
||||
},
|
||||
handlePreview2(row, r2) {
|
||||
if (row.fullPath) {
|
||||
window.open(row.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleUploadFile(param) {
|
||||
this.btnLoading = true
|
||||
const formData = new FormData()
|
||||
formData.append('file', param.file)
|
||||
this.form.FileName = param.file.name
|
||||
// this.form.FileType === 0 ? '既往阅片情况声明' : '入项资格确认书'
|
||||
uploadFile(param.file, this.form.FileType === 0 ? this.$t('trials:enrolledReviews:message:SOW') : this.$t('trials:enrolledReviews:message:EQC'), this.form.DoctorId).then(res => {
|
||||
this.form.FilePath = res.Result.FilePath
|
||||
this.btnLoading = false
|
||||
this.fileList[0] = { name: param.file.name, path: res.Result.FilePath, fullPath: res.Result.FullFilePath }
|
||||
})
|
||||
},
|
||||
handleCancle() {
|
||||
this.model_cfg.visible = false
|
||||
},
|
||||
handleRemoveFile2() {
|
||||
this.form.FileName = null
|
||||
this.form.FilePath = null
|
||||
this.fileList = []
|
||||
},
|
||||
addCol(fileType, row, item) {
|
||||
this.model_cfg.visible = true
|
||||
this.form = {
|
||||
Remark: null,
|
||||
FileType: fileType,
|
||||
FileName: null,
|
||||
FilePath: null,
|
||||
IsEnable: true,
|
||||
TrialId: this.listQuery.TrialId,
|
||||
DoctorId: row.DoctorId,
|
||||
CriterionType: item.CriterionType,
|
||||
CriterionName: item.TrialReadingCriterionName,
|
||||
TrialReadingCriterionId: item.TrialReadingCriterionId
|
||||
}
|
||||
this.handleRemoveFile2()
|
||||
this.model_cfg.title = fileType === 0 ? this.$t('trials:enrolledReviews:message:SOW') : this.$t('trials:enrolledReviews:message:EQC')// '既往阅片情况说明' : '入项资格确认书'
|
||||
},
|
||||
windowOpen(url) {
|
||||
console.log(url)
|
||||
window.open(url)
|
||||
},
|
||||
isEnableChange(row, v) {
|
||||
console.log(row)
|
||||
this.listLoading = true
|
||||
updateTrialReviewerState({
|
||||
TrialId: this.listQuery.TrialId,
|
||||
IsEnable: v,
|
||||
EnrollId: row.EnrollId
|
||||
}).then(res => {
|
||||
// '保存成功'
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleUpdateReadingCategory() {
|
||||
this.readingCategory_model.btnLoading = true
|
||||
this.readingCategory_model.showClose = false
|
||||
var params = {
|
||||
TrialId: this.$route.query.trialId,
|
||||
EnrollId: this.currentRow.EnrollId,
|
||||
ReadingCategorys: Object.assign([], this.ReadingCategorys),
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||
}
|
||||
if (~this.ReadingCategorys.indexOf(1)) {
|
||||
params.ReadingCategorys.push(2)
|
||||
}
|
||||
setEnrollReadingCategory(params)
|
||||
.then(res => {
|
||||
this.readingCategory_model.visible = false
|
||||
this.readingCategory_model.btnLoading = false
|
||||
this.readingCategory_model.showClose = true
|
||||
this.initPage()
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}).catch(_ => {
|
||||
this.readingCategory_model.btnLoading = false
|
||||
this.readingCategory_model.showClose = true
|
||||
})
|
||||
},
|
||||
openSetEnrollReadingCategory(row, TrialReadingCriterionId) {
|
||||
// this.ReadingCategorys = []
|
||||
console.log(row)
|
||||
this.currentRow = row
|
||||
this.TrialReadingCriterionId = TrialReadingCriterionId
|
||||
this.readingCategory_model.visible = true
|
||||
var o = row.CriterionCategoryList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) ? row.CriterionCategoryList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) : null
|
||||
var i = row.TrialReadingCriterionList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) ? row.TrialReadingCriterionList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) : null
|
||||
if (i) {
|
||||
this.IsArbitrationReading = i.IsArbitrationReading
|
||||
this.IsOncologyReading = i.IsOncologyReading
|
||||
}
|
||||
// index不能等于-1(删最后一个元素)和空(删第一个元素)
|
||||
this.ReadingCategorys = Object.assign([], o.ReadingCategorys)
|
||||
this.currentRow.TrialReadingCriterionId = TrialReadingCriterionId
|
||||
var index = o ? o.ReadingCategorys.indexOf(2) : -1
|
||||
if (index >= 0) {
|
||||
this.ReadingCategorys.splice(index, 1)
|
||||
}
|
||||
},
|
||||
// 获取入组医生列表数据
|
||||
initPage() {
|
||||
this.listLoading = true
|
||||
getTrialEnrollmentWorkloadStats(this.listQuery).then((res) => {
|
||||
this.listLoading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
if (this.list.length > 0) {
|
||||
this.TrialReadingCriterionList = this.list[0].TrialReadingCriterionList
|
||||
}
|
||||
this.total = res.Result.TotalCount
|
||||
this.$nextTick(() => {
|
||||
// myTable是表格的ref属性值
|
||||
if (this.$refs.myTable && this.$refs.myTable.doLayout) {
|
||||
this.$refs.myTable.doLayout()
|
||||
}
|
||||
})
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// Enroll按钮回调
|
||||
handleEnroll() {
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel/enrolled-reviewers/enroll?trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}`
|
||||
})
|
||||
},
|
||||
|
||||
// 打开修改状态模态框
|
||||
changeStatus(row) {
|
||||
this.reviewerStatus_model.visible = true
|
||||
this.currentRow = row
|
||||
},
|
||||
|
||||
// 更新医生状态信息
|
||||
handleUpdateReviewerStatus() {
|
||||
this.$refs.updateStatusForm.validate(valid => {
|
||||
if (!valid) return
|
||||
this.reviewerStatus_model.btnLoading = true
|
||||
this.reviewerStatus_model.showClose = false
|
||||
enrollBackOrOut(this.listQuery.TrialId, this.currentRow.DoctorId, this.updateStatusForm.Status)
|
||||
.then(res => {
|
||||
this.$nextTick(() => {
|
||||
this.$refs['updateStatusForm'].resetFields()
|
||||
})
|
||||
this.reviewerStatus_model.btnLoading = false
|
||||
this.reviewerStatus_model.visible = false
|
||||
this.reviewerStatus_model.showClose = true
|
||||
this.initPage()
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.reviewerStatus_model.btnLoading = false
|
||||
this.reviewerStatus_model.showClose = true
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 打开修改reading type模态框
|
||||
handleConfigReadingType(row) {
|
||||
this.readingType_model.visible = true
|
||||
const { ReviewerReadingType } = row
|
||||
this.readingType = ReviewerReadingType
|
||||
this.currentRow = row
|
||||
},
|
||||
|
||||
// 更新 reading type
|
||||
handleUpdateReadingType() {
|
||||
this.readingType_model.btnLoading = true
|
||||
this.readingType_model.showClose = false
|
||||
updateReviewerReadingType(this.listQuery.TrialId, this.currentRow.DoctorId, this.readingType)
|
||||
.then(res => {
|
||||
this.readingType_model.visible = false
|
||||
this.readingType_model.btnLoading = false
|
||||
this.readingType_model.showClose = true
|
||||
this.initPage()
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}).catch(_ => {
|
||||
this.readingType_model.btnLoading = false
|
||||
this.readingType_model.showClose = true
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.listQuery.Asc = true
|
||||
} else {
|
||||
this.listQuery.Asc = false
|
||||
}
|
||||
column.prop === 'EnrollTimeStr'
|
||||
? (this.listQuery.SortField = 'EnrollTime')
|
||||
: (this.listQuery.SortField = column.prop)
|
||||
this.listQuery.PageIndex = 1
|
||||
this.initPage()
|
||||
},
|
||||
|
||||
// 医生详情页跳转
|
||||
handleReviewerDetail(row) {
|
||||
const { href } = this.$router.resolve({ path: `/trials/trials-panel/enrolled-reviewers/resume?doctorId=${row.DoctorId}` })
|
||||
window.open(href, '_blank')
|
||||
},
|
||||
|
||||
// 上传SOW
|
||||
handleUploadAckSow(row) {
|
||||
this.doctorId = row.DoctorId
|
||||
this.currentRow = row
|
||||
this.sow_model.visible = true
|
||||
let fileList = []
|
||||
if (row.AgreementId !== '00000000-0000-0000-0000-000000000000') {
|
||||
fileList = [
|
||||
{
|
||||
DoctorId: row.DoctorId,
|
||||
name: row.AgreementFileName,
|
||||
FileName: row.AgreementFileName,
|
||||
Path: row.AgreementPath,
|
||||
FullPath: row.AgreementFullPath,
|
||||
Type: 'ACK of SOW'
|
||||
}
|
||||
]
|
||||
}
|
||||
this.$nextTick(function() {
|
||||
this.$refs.uploadAckSow.initFileList(fileList)
|
||||
})
|
||||
},
|
||||
|
||||
// 获取上传控件种SOW文件列表
|
||||
getFileList(fileList) {
|
||||
this.currentRow.AgreementId =
|
||||
fileList.length > 0
|
||||
? fileList[0].Id
|
||||
: '00000000-0000-0000-0000-000000000000'
|
||||
this.currentRow.AgreementFileName =
|
||||
fileList.length > 0 ? fileList[0].FileName : ''
|
||||
this.currentRow.AgreementFullPath =
|
||||
fileList.length > 0 ? fileList[0].FullPath : ''
|
||||
this.currentRow.AgreementPath =
|
||||
fileList.length > 0 ? fileList[0].Path : ''
|
||||
},
|
||||
|
||||
// 预览SOW
|
||||
handleViewAckSow(row) {
|
||||
row.AgreementFullPath ? window.open(row.AgreementFullPath, '_blank') : ''
|
||||
},
|
||||
|
||||
// 删除SOW文件
|
||||
handleDeleteAckSOW(row) {
|
||||
this.$confirm(this.$t('trials:enrolledReviews:message:deleteSOWWarning'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
deleteReviewerAckSOW(
|
||||
this.listQuery.TrialId,
|
||||
row.DoctorId,
|
||||
row.AgreementId
|
||||
).then((res) => {
|
||||
row.AgreementId = '00000000-0000-0000-0000-000000000000'
|
||||
row.AgreementFileName = ''
|
||||
row.AgreementFullPath = ''
|
||||
row.AgreementPath = ''
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
})
|
||||
.catch((action) => {})
|
||||
},
|
||||
|
||||
// 跳转工作量统计页
|
||||
handleStats(row) {
|
||||
this.currentClickRowData = row
|
||||
if (row.AgreementId === '00000000-0000-0000-0000-000000000000') {
|
||||
// 'Ack-Sow is not uploaded, continue?'
|
||||
this.$confirm(this.$t('trials:enrolledReviews:message:statsWarning'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.handleTipCloseOK()
|
||||
})
|
||||
.catch(_ => {})
|
||||
} else {
|
||||
this.handleTipCloseOK()
|
||||
}
|
||||
},
|
||||
|
||||
handleTipCloseOK() {
|
||||
zzSessionStorage.setItem(
|
||||
'ReviewerName',
|
||||
this.currentClickRowData.FirstName +
|
||||
' ' +
|
||||
this.currentClickRowData.LastName
|
||||
)
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel/enrolled-reviewers/stats?doctorId=${this.currentClickRowData.DoctorId}&trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}&doctorName=${this.currentClickRowData.LastName}/${this.currentClickRowData.FirstName}`
|
||||
})
|
||||
},
|
||||
|
||||
// 合计行
|
||||
getSummaries(param) {
|
||||
const { columns, data } = param
|
||||
const sums = []
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 1) {
|
||||
sums[index] = 'Total (Current Page)'
|
||||
return
|
||||
}
|
||||
const values = data.map((item) => Number(item[column.property]))
|
||||
if (!values.every((value) => isNaN(value))) {
|
||||
sums[index] = values.reduce((prev, curr) => {
|
||||
const value = Number(curr)
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr
|
||||
} else {
|
||||
return prev
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
return sums
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.enroll-list {
|
||||
height: 100%;
|
||||
.filter-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
Binary file not shown.
|
@ -0,0 +1,354 @@
|
|||
<template>
|
||||
<BaseContainer>
|
||||
<!-- 搜索框 -->
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="器官类型">
|
||||
<el-select v-model="searchData.OrganType" clearable style="width:130px;">
|
||||
<el-option v-for="item of $d.OrganType" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="部位">
|
||||
<el-input v-model="searchData.Part" clearable style="width:130px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="器官">
|
||||
<el-input v-model="searchData.TULOC" clearable style="width:130px;"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否淋巴结">
|
||||
<el-select v-model="searchData.IsLymphNodes" clearable style="width:130px;">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh-left" size="small" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto;">
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem"
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
size="small"
|
||||
@click="handleSet"
|
||||
>
|
||||
设置
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template slot="main-container">
|
||||
<!-- 受试者列表 -->
|
||||
<el-table
|
||||
ref="organList"
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
>
|
||||
<el-table-column type="index" width="90" />
|
||||
<!-- 类型 -->
|
||||
<el-table-column
|
||||
prop="OrganType"
|
||||
label="器官类型"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('OrganType',scope.row.OrganType) }}
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
<!-- 部位 -->
|
||||
<el-table-column
|
||||
prop="Part"
|
||||
label="部位"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="PartEN"
|
||||
label="部位(英文)"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULOC"
|
||||
label="器官"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULOCEN"
|
||||
label="器官(英文)"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULAT"
|
||||
label="位置"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="TULATEN"
|
||||
label="位置(英文)"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="IsLymphNodes"
|
||||
label="是否淋巴结"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsLymphNodes" type="danger">{{ $fd('ReadingYesOrNo', scope.row.IsLymphNodes) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('ReadingYesOrNo', scope.row.IsLymphNodes) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsCanEditPosition"
|
||||
label="是否可以编辑"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsCanEditPosition" type="danger">
|
||||
{{ $fd('YesOrNo', scope.row.IsCanEditPosition) }}
|
||||
</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsCanEditPosition) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="Remark"
|
||||
label="备注"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
label="是否显示"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-if="!isConfirm"
|
||||
v-model="scope.row.IsEnable"
|
||||
@change="changeEnableStatus($event, scope.row)"
|
||||
/>
|
||||
<span v-else>{{ $fd('YesOrNo',scope.row.IsEnable) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<!-- 选择标准 -->
|
||||
<el-dialog
|
||||
v-if="criterion.visible"
|
||||
:visible.sync="criterion.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="criterion.title"
|
||||
width="500px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
ref="criterionForm"
|
||||
v-loading="formLoading"
|
||||
:model="form"
|
||||
size="small"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<!-- 类型 -->
|
||||
<el-form-item
|
||||
label="标准"
|
||||
prop="CriterionId"
|
||||
:rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
|
||||
]"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.CriterionId"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of criterions"
|
||||
:key="item.CriterionId"
|
||||
:label="item.CriterionName"
|
||||
:value="item.CriterionId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button type="primary" @click="criterion.visible = false"> {{ $t('common:button:cancel') }}</el-button>
|
||||
<el-button size="small" type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getTrialOrganList, deleteTrialOrganInfo, getSystemCriterionList, synchronizeSystemOrganToTrial, setOrganIsEnable } from '@/api/trials'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
OrganType: null,
|
||||
TULOC: null,
|
||||
TULAT: null,
|
||||
IsLymphNodes: null,
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'OrgansList',
|
||||
components: { BaseContainer },
|
||||
props: {
|
||||
TrialReadingCriterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isFromSystem: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isConfirm: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
loading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
trialId: '',
|
||||
criterion: { title: '设置', visible: false },
|
||||
formLoading: false,
|
||||
form: { CriterionId: '' },
|
||||
criterions: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
list() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.organList.doLayout()
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCriterions()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 获取受试者列表
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.$route.query.trialId
|
||||
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId
|
||||
getTrialOrganList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result
|
||||
// this.list = res.Result.CurrentPageData
|
||||
// this.total = res.Result.TotalCount
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
// 新增
|
||||
handleAdd() {
|
||||
this.addDialog.visible = true
|
||||
},
|
||||
changeEnableStatus(callback, row) {
|
||||
if (callback) {
|
||||
row.IsEnable = false
|
||||
} else {
|
||||
row.IsEnable = true
|
||||
}
|
||||
var message = '是否确认更改?'
|
||||
this.$confirm(message, {
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const state = !row.IsEnable
|
||||
this.loading = true
|
||||
var params = {
|
||||
isEnable: state,
|
||||
ids: [row.Id]
|
||||
}
|
||||
setOrganIsEnable(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.getList()
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 删除
|
||||
handleDelete(row) {
|
||||
this.$confirm('是否确认删除', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = true
|
||||
deleteTrialOrganInfo(row.Id)
|
||||
.then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
this.$message.success('删除成功!')
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
// this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
getCriterions() {
|
||||
getSystemCriterionList().then(res => {
|
||||
this.criterions = res.Result
|
||||
})
|
||||
},
|
||||
handleSet() {
|
||||
this.criterion.visible = true
|
||||
this.form.CriterionId = ''
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs['criterionForm'].validate((valid) => {
|
||||
if (!valid) return
|
||||
this.formLoading = true
|
||||
var param = {
|
||||
trialId: this.$route.query.trialId,
|
||||
systemCriterionId: this.form.CriterionId
|
||||
}
|
||||
synchronizeSystemOrganToTrial(param).then(res => {
|
||||
this.getList()
|
||||
this.criterion.visible = false
|
||||
this.formLoading = false
|
||||
}).catch(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,392 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<div
|
||||
class="search-form"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<!-- 新增 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && hasPermi(['trials:trials-panel:setting:reading-unit:edit']) && !isFromSystem"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:add') }}
|
||||
</el-button>
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
v-if="isPreview"
|
||||
:disabled="tblList.length===0"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handlePreview"
|
||||
>
|
||||
{{ $t('common:button:preview') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="tblList"
|
||||
size="small"
|
||||
>
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
label=""
|
||||
width="50"
|
||||
/>
|
||||
<!-- 分组 -->
|
||||
<el-table-column
|
||||
prop="GroupName"
|
||||
v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 分组(EN) -->
|
||||
<el-table-column
|
||||
prop="GroupEnName"
|
||||
v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 名称 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 名称(EN) -->
|
||||
<el-table-column
|
||||
prop="QuestionEnName"
|
||||
v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 题型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:readingUnit:qsList:title:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('Criterion_Question_Type',scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:readingUnit:qsList:title:isRequired')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QuestionRequired',scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否显示 -->
|
||||
<el-table-column
|
||||
prop="ShowQuestion"
|
||||
:label="$t('trials:readingUnit:qsList:title:isShow')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('ShowQuestion',scope.row.ShowQuestion) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否裁判问题 -->
|
||||
<el-table-column
|
||||
prop="IsJudgeQuestion"
|
||||
:label="$t('trials:readingUnit:qsList:title:isJudgeQuestion')"
|
||||
width="120"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsJudgeQuestion) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否在阅片页面显示 -->
|
||||
<el-table-column
|
||||
prop="IsShowInDicom"
|
||||
:label="$t('trials:readingUnit:qsList:title:isShowInDicom')"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsShowInDicom) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否在全局阅片显示 -->
|
||||
<el-table-column
|
||||
prop="GlobalReadingShowType"
|
||||
:label="$t('trials:readingUnit:qsList:title:globalReadingShowType')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('GlobalReadingShowType', scope.row.GlobalReadingShowType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 限制编辑 -->
|
||||
<el-table-column
|
||||
prop="LimitEdit"
|
||||
:label="$t('trials:readingUnit:qsList:title:limitEdit')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('LimitEdit', scope.row.LimitEdit) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 注释 -->
|
||||
<el-table-column
|
||||
prop="Remark"
|
||||
:label="$t('trials:readingUnit:qsList:title:Remark')"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('common:action:action')"
|
||||
width="280"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!-- 编辑 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
{{ $t('trials:readingUnit:qsList:title:edit') }}
|
||||
</el-button>
|
||||
<!-- 查看 -->
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handlelook(scope.row)"
|
||||
>
|
||||
{{ $t('trials:readingUnit:qsList:title:view') }}
|
||||
</el-button>
|
||||
<!-- 表格问题 -->
|
||||
<el-button
|
||||
v-if="scope.row.Type === 'table'"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleConfig(scope.row)"
|
||||
>
|
||||
{{ $t('trials:readingUnit:qsList:title:tableQs') }}
|
||||
</el-button>
|
||||
<!-- 删除 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="danger"
|
||||
size="mini"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
{{ $t('trials:readingUnit:qsList:title:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog
|
||||
v-if="addOrEdit.visible"
|
||||
:visible.sync="addOrEdit.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="addOrEdit.title"
|
||||
width="800px"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<QuestionsForm
|
||||
ref="addOrEdit"
|
||||
:data="rowData"
|
||||
:trial-criterion-id="trialCriterionId"
|
||||
:is-from-system="isFromSystem"
|
||||
:digit-places="digitPlaces"
|
||||
:list="tblList"
|
||||
:is-look="isLook"
|
||||
:is-system-criterion="isSystemCriterion"
|
||||
@close="addOrEdit.visible = false"
|
||||
@getList="getList"
|
||||
@reloadArbitrationRules="reloadArbitrationRules"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="preview.visible"
|
||||
:visible.sync="preview.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="preview.title"
|
||||
:fullscreen="true"
|
||||
>
|
||||
<QuestionsPreview :criterion-id="trialCriterionId" :form-type="1" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-if="config.visible"
|
||||
:visible.sync="config.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="config.title"
|
||||
:fullscreen="true"
|
||||
>
|
||||
<TableQsList
|
||||
:digit-places="digitPlaces"
|
||||
:reading-question-id="rowData.Id"
|
||||
:is-from-system="isFromSystem"
|
||||
:is-confirm="isConfirm"
|
||||
:criterion-id="trialCriterionId"
|
||||
@close="config.visible = false"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getReadingQuestionTrialList, deleteReadingQuestionTrial } from '@/api/trials'
|
||||
import QuestionsForm from './QuestionsForm'
|
||||
import QuestionsPreview from './QuestionsPreview'
|
||||
import TableQsList from './TableQsList'
|
||||
import { mapGetters } from 'vuex'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
QuestionName: ''
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'QcQuestions',
|
||||
components: { QuestionsForm, QuestionsPreview, TableQsList },
|
||||
props: {
|
||||
isSystemCriterion: {
|
||||
type: Boolean,
|
||||
default() { return false }
|
||||
},
|
||||
digitPlaces: {
|
||||
type: Number,
|
||||
default() { return 0 }
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() { return [] }
|
||||
},
|
||||
trialCriterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
readingCriterionPageId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isConfirm: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isPreview: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
isFromSystem: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
// list: [],
|
||||
isLook: null,
|
||||
tblList: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
rowData: {},
|
||||
addOrEdit: { visible: false, title: '' },
|
||||
preview: { visible: false, title: this.$t('trials:readingUnit:qsList:title:ecrfPreview') }, // 'eCRF预览'
|
||||
config: { visible: false, title: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.tblList = this.list
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.ReadingQuestionCriterionTrialId = this.trialCriterionId
|
||||
this.searchData.ReadingCriterionPageId = this.readingCriterionPageId
|
||||
getReadingQuestionTrialList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.tblList = res.Result
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleAdd() {
|
||||
this.rowData = {
|
||||
ReadingQuestionCriterionTrialId: this.trialCriterionId,
|
||||
ReadingCriterionPageId: this.readingCriterionPageId,
|
||||
Id: '' }
|
||||
this.isLook = false
|
||||
this.addOrEdit.title = this.$t('trials:readingUnit:qsList:title:add')// '添加'
|
||||
this.addOrEdit.visible = true
|
||||
},
|
||||
handlelook(row) {
|
||||
this.rowData = { ...row }
|
||||
this.isLook = true
|
||||
this.rowData.ReadingQuestionCriterionTrialId = this.trialCriterionId
|
||||
this.rowData.ReadingCriterionPageId = this.readingCriterionPageId
|
||||
this.addOrEdit.title = this.$t('trials:readingUnit:qsList:title:view')// '查看'
|
||||
this.addOrEdit.visible = true
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.rowData = { ...row }
|
||||
this.isLook = false
|
||||
this.rowData.ReadingQuestionCriterionTrialId = this.trialCriterionId
|
||||
this.rowData.ReadingCriterionPageId = this.readingCriterionPageId
|
||||
this.addOrEdit.title = this.$t('trials:readingUnit:qsList:title:edit')// '编辑'
|
||||
this.addOrEdit.visible = true
|
||||
},
|
||||
handleDelete(row) {
|
||||
// '是否确认删除?'
|
||||
this.$confirm(this.$t('trials:readingUnit:qsList:message:deleteConfirm'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = true
|
||||
deleteReadingQuestionTrial(row.Id)
|
||||
.then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
// 删除成功!
|
||||
this.$message.success(this.$t('trials:readingUnit:qsList:message:deleteSuccessfully'))
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
})
|
||||
},
|
||||
handlePreview() {
|
||||
this.preview.visible = true
|
||||
},
|
||||
handleConfig(row) {
|
||||
this.rowData = { ...row }
|
||||
this.config.title = `${this.language === 'en' && row.QuestionEnName ? row.QuestionEnName : row.QuestionName}:${this.$t('trials:readingUnit:qsList:title:tableQs')}`// 表格问题
|
||||
this.config.visible = true
|
||||
},
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.getList()
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
reloadArbitrationRules() {
|
||||
this.$emit('reloadArbitrationRules')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
|
@ -0,0 +1,252 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="globalReadingForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-form-item label="评估结果" prop="GlobalAssessTypes">
|
||||
<div style="width: 700px;display: flex">
|
||||
<el-table
|
||||
min-height="100"
|
||||
style="width: 600px;"
|
||||
ref="multipleTable"
|
||||
:data="form.GlobalAssessTypes"
|
||||
stripe
|
||||
>
|
||||
<el-table-column
|
||||
prop="ValueCN"
|
||||
label="中文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="Value"
|
||||
label="英文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsBaseLineUse"
|
||||
label="是否基线评估"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.IsBaseLineUse"
|
||||
>
|
||||
</el-switch>
|
||||
<span>{{$fd('YesOrNo', scope.row.IsBaseLineUse)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsFollowVisitUse"
|
||||
label="是否随访评估"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.IsFollowVisitUse"
|
||||
>
|
||||
</el-switch>
|
||||
<span>{{$fd('YesOrNo', scope.row.IsFollowVisitUse)}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="display: flex;align-items: center;padding-left: 10px">
|
||||
<el-button
|
||||
:disabled="form.IsSystemCriterion || isSign || !hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
icon="el-icon-plus"
|
||||
circle
|
||||
@click="handleSetCriterion"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="!isSign && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])">
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleSave(true)"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-dialog
|
||||
v-if="config.visible"
|
||||
:visible.sync="config.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="config.title"
|
||||
width="90%"
|
||||
append-to-body
|
||||
>
|
||||
<div style="text-align: right">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleTypeSave"
|
||||
v-loading="loading"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:80}"
|
||||
height="100"
|
||||
ref="multipleTable"
|
||||
:data="$d.GlobalAssessType"
|
||||
stripe
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.ValueCN"
|
||||
label="中文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="raw.Value"
|
||||
label="英文值"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getTrialConfigGlobalReadingInfo, setGlobalReadingInfo } from '@/api/trials'
|
||||
import { getAssessType } from '@/api/dictionary'
|
||||
export default {
|
||||
name: "GlobalReading",
|
||||
props: {
|
||||
TrialReadingCriterionId: {
|
||||
type: String,
|
||||
default() {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
TrialId: '',
|
||||
GlobalAssessTypes: [],
|
||||
IsSystemCriterion: true
|
||||
},
|
||||
rules: {
|
||||
GlobalAssessTypes: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] }]
|
||||
},
|
||||
loading: false,
|
||||
config: { visible: false, title: '全局阅片' },
|
||||
isSign: true,
|
||||
selectedList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
handleSelectionChange(val) {
|
||||
this.selectedList = val
|
||||
},
|
||||
toggleSelection(rows) {
|
||||
console.log(this.$refs.multipleTable)
|
||||
if (rows) {
|
||||
rows.forEach(row => {
|
||||
this.$refs.multipleTable.toggleRowSelection(row);
|
||||
});
|
||||
} else {
|
||||
this.$refs.multipleTable.clearSelection();
|
||||
}
|
||||
},
|
||||
handleSetCriterion() {
|
||||
this.config.visible = true
|
||||
this.$nextTick(() => {
|
||||
var a = this.$d.GlobalAssessType.filter(v => {
|
||||
return !!this.form.GlobalAssessTypes.find(v1 => {
|
||||
return v1.DictionaryId === v.id
|
||||
})
|
||||
})
|
||||
this.toggleSelection(a)
|
||||
})
|
||||
},
|
||||
handleTypeSave() {
|
||||
this.form.GlobalAssessTypes = this.selectedList.map(v => {
|
||||
var o = this.form.GlobalAssessTypes.find(v1 => v1.DictionaryId === v.id)
|
||||
if (o) {
|
||||
return o
|
||||
} else {
|
||||
return {
|
||||
DictionaryId: v.id,
|
||||
ValueCN: v.raw.ValueCN,
|
||||
Value: v.raw.Value,
|
||||
IsBaseLineUse: false,
|
||||
IsFollowVisitUse: false
|
||||
}
|
||||
}
|
||||
})
|
||||
this.config.visible = false
|
||||
},
|
||||
initForm() {
|
||||
this.loading = true
|
||||
getTrialConfigGlobalReadingInfo({ trialId: this.$route.query.trialId, TrialReadingCriterionId: this.TrialReadingCriterionId }).then(res => {
|
||||
if (Object.keys(res.Result).length > 0) {
|
||||
for (const k in res.Result) {
|
||||
if (this.form.hasOwnProperty(k)) {
|
||||
this.form[k] = res.Result[k]
|
||||
}
|
||||
}
|
||||
this.isSign = res.Result.IsSign
|
||||
}
|
||||
this.form.GlobalAssessTypeIdsStr = this.form.GlobalAssessTypeIds.map(v => this.$fd('GlobalAssessType', v, 'id')).toString()
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSave(isPrompt) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.$refs['globalReadingForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
reject(false)
|
||||
} else {
|
||||
this.loading = true
|
||||
// 保存配置信息
|
||||
this.form.TrialId = this.$route.query.trialId
|
||||
this.form.TrialReadingCriterionId = this.TrialReadingCriterionId
|
||||
var params = {
|
||||
GlobalAssessList: this.form.GlobalAssessTypes,
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId,
|
||||
TrialId: this.$route.query.trialId
|
||||
}
|
||||
setGlobalReadingInfo(params).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess && isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
resolve(true)
|
||||
}).catch(_ => {
|
||||
this.loading = false
|
||||
reject(false)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,257 @@
|
|||
<template>
|
||||
<el-form
|
||||
ref="sysTemplateFrom"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
label-width="90px"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
class="upload-temporary-file"
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="Code" prop="Code">
|
||||
<el-input v-model="form.Code" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务场景: " prop="BusinessScenarioEnum">
|
||||
<el-select
|
||||
v-model="form.BusinessScenarioEnum"
|
||||
style="width:100%;"
|
||||
size="small"
|
||||
filterable
|
||||
disabled
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Common_File_BusinessScenario"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文件: ">
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
accept=".xls,.xlsx,.doc,.docx"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemoveFile"
|
||||
:show-file-list="true"
|
||||
:file-list="fileList"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum">Select</el-button>
|
||||
<span
|
||||
slot="tip"
|
||||
style="margin-left:10px;"
|
||||
class="el-upload__tip"
|
||||
>
|
||||
(must be in xlsx/xls/doc/docx format)
|
||||
</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="阅片标准: " prop="CriterionTypeEnum">
|
||||
<el-select
|
||||
v-model="form.CriterionTypeEnum"
|
||||
style="width:100%;"
|
||||
size="small"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.CriterionType"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
||||
<el-radio-group v-model="form.IsDeleted">
|
||||
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input
|
||||
v-model="form.Description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
placeholder="请输入内容"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum" @click="handleSave">Save</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateCommonDocument, uploadCommonDoc } from '@/api/dictionary'
|
||||
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
|
||||
export default {
|
||||
name: 'TemplateForm',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
},
|
||||
isDistinguishCriteria: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
Id: '',
|
||||
Code: '',
|
||||
FileTypeEnum: null,
|
||||
BusinessScenarioEnum: null,
|
||||
CriterionTypeEnum: null,
|
||||
Name: '',
|
||||
Path: '',
|
||||
Description: '',
|
||||
IsDeleted: false
|
||||
},
|
||||
rules: {
|
||||
Code: [{ required: true, message: 'Please specify', trigger: ['blur'] }],
|
||||
CriterionTypeEnum: [{ required: this.isDistinguishCriteria, message: 'Please select', trigger: ['blur'] }],
|
||||
BusinessScenarioEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }]
|
||||
},
|
||||
fileList: [],
|
||||
loading: false,
|
||||
dictionaryList: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getDicData()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
if (this.data.Path) {
|
||||
this.fileList = [
|
||||
{
|
||||
name: this.data.Name,
|
||||
path: this.data.Path,
|
||||
type: this.data.Type
|
||||
}
|
||||
]
|
||||
}
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取文件类型下拉框
|
||||
getDicData() {
|
||||
this.loading = true
|
||||
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type']).then(res => {
|
||||
this.dictionaryList = { ...res.Result }
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
this.fileList = []
|
||||
return true
|
||||
} else {
|
||||
this.$alert('必须是word/excel格式')
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
handleUploadFile(param) {
|
||||
this.loading = true
|
||||
uploadCommonDoc(param.file).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.form.Path = res.Result.FilePath
|
||||
this.form.Name = param.file.name
|
||||
const file = { name: this.form.Name, path: this.form.Path }
|
||||
this.fileList.push(file)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs.sysTemplateFrom.validate(valid => {
|
||||
if (!valid) return
|
||||
if (!this.form.Name) {
|
||||
this.$alert('Please select file.')
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
addOrUpdateCommonDocument(this.form).then(res => {
|
||||
this.loading = false
|
||||
this.$emit('closeDialog')
|
||||
this.$emit('getList')
|
||||
this.$message.success('保存成功!')
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleRemoveFile() {
|
||||
this.fileList = []
|
||||
this.form.Path = ''
|
||||
this.form.Name = ''
|
||||
},
|
||||
handlePreview(file) {
|
||||
if (file.fullPath) {
|
||||
window.open(file.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(`Upload is currently limited to 1 file`)
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var typeArr = ['xls', 'xlsx', 'doc', 'docx']
|
||||
var extendName = fileName.substring(fileName.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) !== -1) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-temporary-file{
|
||||
.upload-container .el-upload--text {
|
||||
border: none;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
.upload-container .el-input--small {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-container .el-icon-circle-check {
|
||||
color: #428bca;
|
||||
font-size: 13px;
|
||||
}
|
||||
.account_item_clear{
|
||||
.el-tag__close{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue